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/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/schema/test_parser_yang.c b/tests/utests/schema/test_parser_yang.c
new file mode 100644
index 0000000..6311dfc
--- /dev/null
+++ b/tests/utests/schema/test_parser_yang.c
@@ -0,0 +1,2262 @@
+/*
+ * @file test_parser_yang.c
+ * @author: Radek Krejci <rkrejci@cesnet.cz>
+ * @brief unit tests for functions from parser_yang.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 <setjmp.h>
+#include <cmocka.h>
+
+#include <stdio.h>
+#include <string.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_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);
+void lysp_notif_free(struct ly_ctx *ctx, struct lysp_notif *notif);
+void lysp_augment_free(struct ly_ctx *ctx, struct lysp_augment *augment);
+void lysp_deviate_free(struct ly_ctx *ctx, struct lysp_deviate *d);
+void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node);
+void lysp_when_free(struct ly_ctx *ctx, struct lysp_when *when);
+
+LY_ERR buf_add_char(struct ly_ctx *ctx, const char **input, size_t len, char **buf, size_t *buf_len, size_t *buf_used);
+LY_ERR buf_store_char(struct lys_yang_parser_ctx *ctx, const char **input, enum yang_arg arg, char **word_p,
+                      size_t *word_len, char **word_b, size_t *buf_len, int need_buf, int *prefix);
+LY_ERR get_keyword(struct lys_yang_parser_ctx *ctx, const char **data, enum ly_stmt *kw, char **word_p, size_t *word_len);
+LY_ERR get_argument(struct lys_yang_parser_ctx *ctx, const char **data, enum yang_arg arg,
+                    uint16_t *flags, char **word_p, char **word_b, size_t *word_len);
+LY_ERR skip_comment(struct lys_yang_parser_ctx *ctx, const char **data, int comment);
+
+LY_ERR parse_action(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_action **actions);
+LY_ERR parse_any(struct lys_yang_parser_ctx *ctx, const char **data, enum ly_stmt kw, struct lysp_node *parent, struct lysp_node **siblings);
+LY_ERR parse_augment(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_augment **augments);
+LY_ERR parse_case(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
+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_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_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);
+LY_ERR parse_maxelements(struct lys_yang_parser_ctx *ctx, const char **data, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts);
+LY_ERR parse_minelements(struct lys_yang_parser_ctx *ctx, const char **data, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts);
+LY_ERR parse_module(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_module *mod);
+LY_ERR parse_notif(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_notif **notifs);
+LY_ERR parse_submodule(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_submodule *submod);
+LY_ERR parse_uses(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_node *parent, struct lysp_node **siblings);
+LY_ERR parse_when(struct lys_yang_parser_ctx *ctx, const char **data, struct lysp_when **when_p);
+LY_ERR parse_type_enum_value_pos(struct lys_yang_parser_ctx *ctx, const char **data, enum ly_stmt val_kw, int64_t *value, uint16_t *flags, struct lysp_ext_instance **exts);
+
+#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
+    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
+
+#define TEST_DUP_GENERIC(PREFIX, MEMBER, VALUE1, VALUE2, FUNC, RESULT, LINE, CLEANUP) \
+    str = PREFIX MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, FUNC(&ctx, &str, RESULT)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number "LINE"."); \
+    CLEANUP
+
+static void
+test_helpers(void **state)
+{
+    (void) state; /* unused */
+
+    const char *str;
+    char *buf, *p;
+    size_t len, size;
+    struct lys_yang_parser_ctx ctx;
+    ctx.format = LYS_IN_YANG;
+    ctx.ctx = NULL;
+    ctx.pos_type = LY_VLOG_LINE;
+    ctx.line = 1;
+    int prefix = 0;
+
+    /* storing into buffer */
+    str = "abcd";
+    buf = NULL;
+    size = len = 0;
+    assert_int_equal(LY_SUCCESS, buf_add_char(NULL, &str, 2, &buf, &size, &len));
+    assert_int_not_equal(0, size);
+    assert_int_equal(2, len);
+    assert_string_equal("cd", str);
+    assert_false(strncmp("ab", buf, 2));
+    free(buf);
+    buf = NULL;
+
+    /* invalid first characters */
+    len = 0;
+    str = "2invalid";
+    assert_int_equal(LY_EVALID, buf_store_char(&ctx, &str, Y_IDENTIF_ARG, &p, &len, &buf, &size, 1, &prefix));
+    str = ".invalid";
+    assert_int_equal(LY_EVALID, buf_store_char(&ctx, &str, Y_IDENTIF_ARG, &p, &len, &buf, &size, 1, &prefix));
+    str = "-invalid";
+    assert_int_equal(LY_EVALID, buf_store_char(&ctx, &str, Y_IDENTIF_ARG, &p, &len, &buf, &size, 1, &prefix));
+    /* invalid following characters */
+    len = 3; /* number of characters read before the str content */
+    str = "!";
+    assert_int_equal(LY_EVALID, buf_store_char(&ctx, &str, Y_IDENTIF_ARG, &p, &len, &buf, &size, 1, &prefix));
+    str = ":";
+    assert_int_equal(LY_EVALID, buf_store_char(&ctx, &str, Y_IDENTIF_ARG, &p, &len, &buf, &size, 1, &prefix));
+    /* valid colon for prefixed identifiers */
+    len = size = 0;
+    p = NULL;
+    prefix = 0;
+    str = "x:id";
+    assert_int_equal(LY_SUCCESS, buf_store_char(&ctx, &str, Y_PREF_IDENTIF_ARG, &p, &len, &buf, &size, 0, &prefix));
+    assert_int_equal(1, len);
+    assert_null(buf);
+    assert_string_equal(":id", str);
+    assert_int_equal('x', p[len - 1]);
+    assert_int_equal(LY_SUCCESS, buf_store_char(&ctx, &str, Y_PREF_IDENTIF_ARG, &p, &len, &buf, &size, 1, &prefix));
+    assert_int_equal(2, len);
+    assert_string_equal("id", str);
+    assert_int_equal(':', p[len - 1]);
+    free(buf);
+    prefix = 0;
+
+    /* checking identifiers */
+    assert_int_equal(LY_EVALID, lysp_check_identifierchar((struct lys_parser_ctx *)&ctx, ':', 0, NULL));
+    logbuf_assert("Invalid identifier character ':'. Line number 1.");
+    assert_int_equal(LY_EVALID, lysp_check_identifierchar((struct lys_parser_ctx *)&ctx, '#', 1, NULL));
+    logbuf_assert("Invalid identifier first character '#'. Line number 1.");
+
+    assert_int_equal(LY_SUCCESS, lysp_check_identifierchar((struct lys_parser_ctx *)&ctx, 'a', 1, &prefix));
+    assert_int_equal(0, prefix);
+    assert_int_equal(LY_SUCCESS, lysp_check_identifierchar((struct lys_parser_ctx *)&ctx, ':', 0, &prefix));
+    assert_int_equal(1, prefix);
+    assert_int_equal(LY_EVALID, lysp_check_identifierchar((struct lys_parser_ctx *)&ctx, ':', 0, &prefix));
+    assert_int_equal(1, prefix);
+    assert_int_equal(LY_SUCCESS, lysp_check_identifierchar((struct lys_parser_ctx *)&ctx, 'b', 0, &prefix));
+    assert_int_equal(2, prefix);
+    /* second colon is invalid */
+    assert_int_equal(LY_EVALID, lysp_check_identifierchar((struct lys_parser_ctx *)&ctx, ':', 0, &prefix));
+    logbuf_assert("Invalid identifier character ':'. Line number 1.");
+}
+
+static void
+test_comments(void **state)
+{
+    (void) state; /* unused */
+
+    struct lys_yang_parser_ctx ctx;
+    const char *str, *p;
+    char *word, *buf;
+    size_t len;
+
+    ctx.format = LYS_IN_YANG;
+    ctx.ctx = NULL;
+    ctx.pos_type = LY_VLOG_LINE;
+    ctx.line = 1;
+
+    str = " // this is a text of / one * line */ comment\nargument;";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_string_equal("argument;", word);
+    assert_null(buf);
+    assert_int_equal(8, len);
+
+    str = "/* this is a \n * text // of / block * comment */\"arg\" + \"ume\" \n + \n \"nt\";";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_string_equal("argument", word);
+    assert_ptr_equal(buf, word);
+    assert_int_equal(8, len);
+    free(word);
+
+    str = p = " this is one line comment on last line";
+    assert_int_equal(LY_SUCCESS, skip_comment(&ctx, &str, 1));
+    assert_true(str[0] == '\0');
+
+    str = p = " this is a not terminated comment x";
+    assert_int_equal(LY_EVALID, skip_comment(&ctx, &str, 2));
+    logbuf_assert("Unexpected end-of-input, non-terminated comment. Line number 5.");
+    assert_true(str[0] == '\0');
+}
+
+static void
+test_arg(void **state)
+{
+    (void) state; /* unused */
+
+    struct lys_yang_parser_ctx ctx;
+    const char *str;
+    char *word, *buf;
+    size_t len;
+
+    ctx.format = LYS_IN_YANG;
+    ctx.ctx = NULL;
+    ctx.pos_type = LY_VLOG_LINE;
+    ctx.line = 1;
+
+    /* missing argument */
+    str = ";";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_MAYBE_STR_ARG, NULL, &word, &buf, &len));
+    assert_null(word);
+
+    str = "{";
+    assert_int_equal(LY_EVALID, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    logbuf_assert("Invalid character sequence \"{\", expected an argument. Line number 1.");
+
+    /* invalid escape sequence */
+    str = "\"\\s\"";
+    assert_int_equal(LY_EVALID, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    logbuf_assert("Double-quoted string unknown special character \'\\s\'. Line number 1.");
+    str = "\'\\s\'"; /* valid, since it is not an escape sequence in single quoted string */
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_int_equal(2, len);
+    assert_string_equal("\\s\'", word);
+    assert_int_equal('\0', str[0]); /* input has been eaten */
+
+    /* invalid character after the argument */
+    str = "hello\"";
+    assert_int_equal(LY_EVALID, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    logbuf_assert("Invalid character sequence \"\"\", expected unquoted string character, optsep, semicolon or opening brace. Line number 1.");
+    str = "hello}";
+    assert_int_equal(LY_EVALID, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    logbuf_assert("Invalid character sequence \"}\", expected unquoted string character, optsep, semicolon or opening brace. Line number 1.");
+
+    /* invalid identifier-ref-arg-str */
+    str = "pre:pre:value";
+    assert_int_equal(LY_EVALID, get_argument(&ctx, &str, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &len));
+
+    str = "\"\";"; /* empty identifier is not allowed */
+    assert_int_equal(LY_EVALID, get_argument(&ctx, &str, Y_IDENTIF_ARG, NULL, &word, &buf, &len));
+    logbuf_assert("Statement argument is required. Line number 1.");
+    logbuf_clean();
+    str = "\"\";"; /* empty reference identifier is not allowed */
+    assert_int_equal(LY_EVALID, get_argument(&ctx, &str, Y_PREF_IDENTIF_ARG, NULL, &word, &buf, &len));
+    logbuf_assert("Statement argument is required. Line number 1.");
+
+    str = "hello/x\t"; /* slash is not an invalid character */
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_int_equal(7, len);
+    assert_string_equal("hello/x\t", word);
+
+    assert_null(buf);
+
+    /* different quoting */
+    str = "hello ";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_null(buf);
+    assert_int_equal(5, len);
+    assert_string_equal("hello ", word);
+
+    str = "hello/*comment*/\n";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_null(buf);
+    assert_int_equal(5, len);
+    assert_false(strncmp("hello", word, len));
+
+
+    str = "\"hello\\n\\t\\\"\\\\\";";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_non_null(buf);
+    assert_int_equal(9, len);
+    assert_string_equal("hello\n\t\"\\", word);
+    free(buf);
+
+    ctx.indent = 14;
+    str = "\"hello \t\n\t\t world!\"";
+    /* - space and tabs before newline are stripped out
+     * - space and tabs after newline (indentation) are stripped out
+     */
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_non_null(buf);
+    assert_ptr_equal(word, buf);
+    assert_int_equal(14, len);
+    assert_string_equal("hello\n  world!", word);
+    free(buf);
+    /* In contrast to previous, the backslash-escaped tabs are expanded after trimming, so they are preserved */
+    ctx.indent = 14;
+    str = "\"hello \\t\n\t\\t world!\"";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_non_null(buf);
+    assert_ptr_equal(word, buf);
+    assert_int_equal(16, len);
+    assert_string_equal("hello \t\n\t world!", word);
+    free(buf);
+    /* Do not handle whitespaces after backslash-escaped newline as indentation */
+    ctx.indent = 14;
+    str = "\"hello\\n\t\t world!\"";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_non_null(buf);
+    assert_ptr_equal(word, buf);
+    assert_int_equal(15, len);
+    assert_string_equal("hello\n\t\t world!", word);
+    free(buf);
+
+    ctx.indent = 14;
+    str = "\"hello\n \tworld!\"";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_non_null(buf);
+    assert_ptr_equal(word, buf);
+    assert_int_equal(12, len);
+    assert_string_equal("hello\nworld!", word);
+    free(buf);
+
+    str = "\'hello\'";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_null(buf);
+    assert_int_equal(5, len);
+    assert_false(strncmp("hello", word, 5));
+
+    str = "\"hel\"  +\t\n\"lo\"";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_ptr_equal(word, buf);
+    assert_int_equal(5, len);
+    assert_string_equal("hello", word);
+    free(buf);
+    str = "\"hel\"  +\t\nlo"; /* unquoted the second part */
+    assert_int_equal(LY_EVALID, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    logbuf_assert("Both string parts divided by '+' must be quoted. Line number 6.");
+
+    str = "\'he\'\t\n+ \"llo\"";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_ptr_equal(word, buf);
+    assert_int_equal(5, len);
+    assert_string_equal("hello", word);
+    free(buf);
+
+    str = " \t\n\"he\"+\'llo\'";
+    assert_int_equal(LY_SUCCESS, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    assert_ptr_equal(word, buf);
+    assert_int_equal(5, len);
+    assert_string_equal("hello", word);
+    free(buf);
+
+    /* missing argument */
+    str = ";";
+    assert_int_equal(LY_EVALID, get_argument(&ctx, &str, Y_STR_ARG, NULL, &word, &buf, &len));
+    logbuf_assert("Invalid character sequence \";\", expected an argument. Line number 8.");
+}
+
+static void
+test_stmts(void **state)
+{
+    (void) state; /* unused */
+
+    struct lys_yang_parser_ctx ctx;
+    const char *str, *p;
+    enum ly_stmt kw;
+    char *word;
+    size_t len;
+
+    ctx.format = LYS_IN_YANG;
+    ctx.ctx = NULL;
+    ctx.pos_type = LY_VLOG_LINE;
+    ctx.line = 1;
+
+    str = "\n// comment\n\tinput\t{";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_INPUT, kw);
+    assert_int_equal(5, len);
+    assert_string_equal("input\t{", word);
+    assert_string_equal("\t{", str);
+
+    str = "\t /* comment */\t output\n\t{";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_OUTPUT, kw);
+    assert_int_equal(6, len);
+    assert_string_equal("output\n\t{", word);
+    assert_string_equal("\n\t{", str);
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_SYNTAX_LEFT_BRACE, kw);
+    assert_int_equal(1, len);
+    assert_string_equal("{", word);
+    assert_string_equal("", str);
+
+    str = "/input { "; /* invalid slash */
+    assert_int_equal(LY_EVALID, get_keyword(&ctx, &str, &kw, &word, &len));
+    logbuf_assert("Invalid identifier first character '/'. Line number 4.");
+
+    str = "not-a-statement-nor-extension { "; /* invalid identifier */
+    assert_int_equal(LY_EVALID, get_keyword(&ctx, &str, &kw, &word, &len));
+    logbuf_assert("Invalid character sequence \"not-a-statement-nor-extension\", expected a keyword. Line number 4.");
+
+    str = "path;"; /* missing sep after the keyword */
+    assert_int_equal(LY_EVALID, get_keyword(&ctx, &str, &kw, &word, &len));
+    logbuf_assert("Invalid character sequence \"path;\", expected a keyword followed by a separator. Line number 4.");
+
+    str = "action ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_ACTION, kw);
+    assert_int_equal(6, len);
+    str = "anydata ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_ANYDATA, kw);
+    assert_int_equal(7, len);
+    str = "anyxml ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_ANYXML, kw);
+    assert_int_equal(6, len);
+    str = "argument ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_ARGUMENT, kw);
+    assert_int_equal(8, len);
+    str = "augment ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_AUGMENT, kw);
+    assert_int_equal(7, len);
+    str = "base ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_BASE, kw);
+    assert_int_equal(4, len);
+    str = "belongs-to ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_BELONGS_TO, kw);
+    assert_int_equal(10, len);
+    str = "bit ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_BIT, kw);
+    assert_int_equal(3, len);
+    str = "case ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_CASE, kw);
+    assert_int_equal(4, len);
+    str = "choice ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_CHOICE, kw);
+    assert_int_equal(6, len);
+    str = "config ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_CONFIG, kw);
+    assert_int_equal(6, len);
+    str = "contact ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_CONTACT, kw);
+    assert_int_equal(7, len);
+    str = "container ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_CONTAINER, kw);
+    assert_int_equal(9, len);
+    str = "default ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_DEFAULT, kw);
+    assert_int_equal(7, len);
+    str = "description ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_DESCRIPTION, kw);
+    assert_int_equal(11, len);
+    str = "deviate ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_DEVIATE, kw);
+    assert_int_equal(7, len);
+    str = "deviation ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_DEVIATION, kw);
+    assert_int_equal(9, len);
+    str = "enum ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_ENUM, kw);
+    assert_int_equal(4, len);
+    str = "error-app-tag ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_ERROR_APP_TAG, kw);
+    assert_int_equal(13, len);
+    str = "error-message ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_ERROR_MESSAGE, kw);
+    assert_int_equal(13, len);
+    str = "extension ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_EXTENSION, kw);
+    assert_int_equal(9, len);
+    str = "feature ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_FEATURE, kw);
+    assert_int_equal(7, len);
+    str = "fraction-digits ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_FRACTION_DIGITS, kw);
+    assert_int_equal(15, len);
+    str = "grouping ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_GROUPING, kw);
+    assert_int_equal(8, len);
+    str = "identity ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_IDENTITY, kw);
+    assert_int_equal(8, len);
+    str = "if-feature ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_IF_FEATURE, kw);
+    assert_int_equal(10, len);
+    str = "import ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_IMPORT, kw);
+    assert_int_equal(6, len);
+    str = "include ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_INCLUDE, kw);
+    assert_int_equal(7, len);
+    str = "input{";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_INPUT, kw);
+    assert_int_equal(5, len);
+    str = "key ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_KEY, kw);
+    assert_int_equal(3, len);
+    str = "leaf ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_LEAF, kw);
+    assert_int_equal(4, len);
+    str = "leaf-list ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_LEAF_LIST, kw);
+    assert_int_equal(9, len);
+    str = "length ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_LENGTH, kw);
+    assert_int_equal(6, len);
+    str = "list ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_LIST, kw);
+    assert_int_equal(4, len);
+    str = "mandatory ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_MANDATORY, kw);
+    assert_int_equal(9, len);
+    str = "max-elements ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_MAX_ELEMENTS, kw);
+    assert_int_equal(12, len);
+    str = "min-elements ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_MIN_ELEMENTS, kw);
+    assert_int_equal(12, len);
+    str = "modifier ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_MODIFIER, kw);
+    assert_int_equal(8, len);
+    str = "module ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_MODULE, kw);
+    assert_int_equal(6, len);
+    str = "must ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_MUST, kw);
+    assert_int_equal(4, len);
+    str = "namespace ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_NAMESPACE, kw);
+    assert_int_equal(9, len);
+    str = "notification ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_NOTIFICATION, kw);
+    assert_int_equal(12, len);
+    str = "ordered-by ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_ORDERED_BY, kw);
+    assert_int_equal(10, len);
+    str = "organization ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_ORGANIZATION, kw);
+    assert_int_equal(12, len);
+    str = "output ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_OUTPUT, kw);
+    assert_int_equal(6, len);
+    str = "path ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_PATH, kw);
+    assert_int_equal(4, len);
+    str = "pattern ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_PATTERN, kw);
+    assert_int_equal(7, len);
+    str = "position ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_POSITION, kw);
+    assert_int_equal(8, len);
+    str = "prefix ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_PREFIX, kw);
+    assert_int_equal(6, len);
+    str = "presence ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_PRESENCE, kw);
+    assert_int_equal(8, len);
+    str = "range ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_RANGE, kw);
+    assert_int_equal(5, len);
+    str = "reference ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_REFERENCE, kw);
+    assert_int_equal(9, len);
+    str = "refine ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_REFINE, kw);
+    assert_int_equal(6, len);
+    str = "require-instance ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_REQUIRE_INSTANCE, kw);
+    assert_int_equal(16, len);
+    str = "revision ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_REVISION, kw);
+    assert_int_equal(8, len);
+    str = "revision-date ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_REVISION_DATE, kw);
+    assert_int_equal(13, len);
+    str = "rpc ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_RPC, kw);
+    assert_int_equal(3, len);
+    str = "status ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_STATUS, kw);
+    assert_int_equal(6, len);
+    str = "submodule ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_SUBMODULE, kw);
+    assert_int_equal(9, len);
+    str = "type ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_TYPE, kw);
+    assert_int_equal(4, len);
+    str = "typedef ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_TYPEDEF, kw);
+    assert_int_equal(7, len);
+    str = "unique ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_UNIQUE, kw);
+    assert_int_equal(6, len);
+    str = "units ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_UNITS, kw);
+    assert_int_equal(5, len);
+    str = "uses ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_USES, kw);
+    assert_int_equal(4, len);
+    str = "value ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_VALUE, kw);
+    assert_int_equal(5, len);
+    str = "when ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_WHEN, kw);
+    assert_int_equal(4, len);
+    str = "yang-version ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_YANG_VERSION, kw);
+    assert_int_equal(12, len);
+    str = "yin-element ";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_YIN_ELEMENT, kw);
+    assert_int_equal(11, len);
+    str = ";config false;";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_SYNTAX_SEMICOLON, kw);
+    assert_int_equal(1, len);
+    assert_string_equal("config false;", str);
+    str = "{ config false;";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_SYNTAX_LEFT_BRACE, kw);
+    assert_int_equal(1, len);
+    assert_string_equal(" config false;", str);
+    str = "}";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_SYNTAX_RIGHT_BRACE, kw);
+    assert_int_equal(1, len);
+    assert_string_equal("", str);
+
+    /* geenric extension */
+    str = p = "nacm:default-deny-write;";
+    assert_int_equal(LY_SUCCESS, get_keyword(&ctx, &str, &kw, &word, &len));
+    assert_int_equal(LY_STMT_EXTENSION_INSTANCE, kw);
+    assert_int_equal(23, len);
+    assert_ptr_equal(p, word);
+}
+
+static void
+test_minmax(void **state)
+{
+    *state = test_minmax;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    uint16_t flags = 0;
+    uint32_t value = 0;
+    struct lysp_ext_instance *ext = 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.mod_version = 2; /* simulate YANG 1.1 */
+
+    str = " 1invalid; ...";
+    assert_int_equal(LY_EVALID, parse_minelements(&ctx, &str, &value, &flags, &ext));
+    logbuf_assert("Invalid value \"1invalid\" of \"min-elements\". Line number 1.");
+
+    flags = value = 0;
+    str = " -1; ...";
+    assert_int_equal(LY_EVALID, parse_minelements(&ctx, &str, &value, &flags, &ext));
+    logbuf_assert("Invalid value \"-1\" of \"min-elements\". Line number 1.");
+
+    /* implementation limit */
+    flags = value = 0;
+    str = " 4294967296; ...";
+    assert_int_equal(LY_EVALID, parse_minelements(&ctx, &str, &value, &flags, &ext));
+    logbuf_assert("Value \"4294967296\" is out of \"min-elements\" bounds. Line number 1.");
+
+    flags = value = 0;
+    str = " 1; ...";
+    assert_int_equal(LY_SUCCESS, parse_minelements(&ctx, &str, &value, &flags, &ext));
+    assert_int_equal(LYS_SET_MIN, flags);
+    assert_int_equal(1, value);
+
+    flags = value = 0;
+    str = " 1 {m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_minelements(&ctx, &str, &value, &flags, &ext));
+    assert_int_equal(LYS_SET_MIN, flags);
+    assert_int_equal(1, value);
+    assert_non_null(ext);
+    FREE_ARRAY(ctx.ctx, ext, lysp_ext_instance_free);
+    ext = NULL;
+
+    flags = value = 0;
+    str = " 1 {config true;} ...";
+    assert_int_equal(LY_EVALID, parse_minelements(&ctx, &str, &value, &flags, &ext));
+    logbuf_assert("Invalid keyword \"config\" as a child of \"min-elements\". Line number 1.");
+
+    str = " 1invalid; ...";
+    assert_int_equal(LY_EVALID, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+    logbuf_assert("Invalid value \"1invalid\" of \"max-elements\". Line number 1.");
+
+    flags = value = 0;
+    str = " -1; ...";
+    assert_int_equal(LY_EVALID, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+    logbuf_assert("Invalid value \"-1\" of \"max-elements\". Line number 1.");
+
+    /* implementation limit */
+    flags = value = 0;
+    str = " 4294967296; ...";
+    assert_int_equal(LY_EVALID, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+    logbuf_assert("Value \"4294967296\" is out of \"max-elements\" bounds. Line number 1.");
+
+    flags = value = 0;
+    str = " 1; ...";
+    assert_int_equal(LY_SUCCESS, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+    assert_int_equal(LYS_SET_MAX, flags);
+    assert_int_equal(1, value);
+
+    flags = value = 0;
+    str = " unbounded; ...";
+    assert_int_equal(LY_SUCCESS, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+    assert_int_equal(LYS_SET_MAX, flags);
+    assert_int_equal(0, value);
+
+    flags = value = 0;
+    str = " 1 {m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+    assert_int_equal(LYS_SET_MAX, flags);
+    assert_int_equal(1, value);
+    assert_non_null(ext);
+    FREE_ARRAY(ctx.ctx, ext, lysp_ext_instance_free);
+    ext = NULL;
+
+    flags = value = 0;
+    str = " 1 {config true;} ...";
+    assert_int_equal(LY_EVALID, parse_maxelements(&ctx, &str, &value, &flags, &ext));
+    logbuf_assert("Invalid keyword \"config\" as a child of \"max-elements\". Line number 1.");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static struct lysp_module *
+mod_renew(struct lys_yang_parser_ctx *ctx)
+{
+    struct lysp_module *mod_p;
+    static struct lys_module mod = {0};
+
+    lysc_module_free(mod.compiled, NULL);
+    lysp_module_free(mod.parsed);
+    FREE_STRING(mod.ctx, mod.name);
+    FREE_STRING(mod.ctx, mod.ns);
+    FREE_STRING(mod.ctx, mod.prefix);
+    FREE_STRING(mod.ctx, mod.filepath);
+    FREE_STRING(mod.ctx, mod.org);
+    FREE_STRING(mod.ctx, mod.contact);
+    FREE_STRING(mod.ctx, mod.dsc);
+    FREE_STRING(mod.ctx, mod.ref);
+    memset(&mod, 0, sizeof mod);
+    mod.ctx = ctx->ctx;
+
+    mod_p = calloc(1, sizeof *mod_p);
+    mod.parsed = mod_p;
+    mod_p->mod = &mod;
+    assert_non_null(mod_p);
+    return mod_p;
+}
+
+static struct lysp_submodule *
+submod_renew(struct lys_yang_parser_ctx *ctx, struct lysp_submodule *submod)
+{
+    lysp_submodule_free(ctx->ctx, submod);
+    submod = calloc(1, sizeof *submod);
+    assert_non_null(submod);
+    return submod;
+}
+
+static LY_ERR test_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const char *UNUSED(submod_name),
+                           const char *UNUSED(sub_rev), void *user_data, LYS_INFORMAT *format,
+                           const char **module_data, void (**free_module_data)(void *model_data, void *user_data))
+{
+    *module_data = user_data;
+    *format = LYS_IN_YANG;
+    *free_module_data = NULL;
+    return LY_SUCCESS;
+}
+
+static void
+test_module(void **state)
+{
+    *state = test_module;
+
+    struct lys_yang_parser_ctx ctx;
+    struct lysp_module *mod = NULL;
+    struct lysp_submodule *submod = NULL;
+    struct lys_module *m;
+    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;
+
+    mod = mod_renew(&ctx);
+
+    /* missing mandatory substatements */
+    str = " name {}";
+    assert_int_equal(LY_EVALID, parse_module(&ctx, &str, mod));
+    assert_string_equal("name", mod->mod->name);
+    logbuf_assert("Missing mandatory keyword \"namespace\" as a child of \"module\". Line number 1.");
+    mod = mod_renew(&ctx);
+
+    str = " name {namespace urn:x;}";
+    assert_int_equal(LY_EVALID, parse_module(&ctx, &str, mod));
+    assert_string_equal("urn:x", mod->mod->ns);
+    logbuf_assert("Missing mandatory keyword \"prefix\" as a child of \"module\". Line number 1.");
+    mod = mod_renew(&ctx);
+
+    str = " name {namespace urn:x;prefix \"x\";}";
+    assert_int_equal(LY_SUCCESS, parse_module(&ctx, &str, mod));
+    assert_string_equal("x", mod->mod->prefix);
+    mod = mod_renew(&ctx);
+
+#define SCHEMA_BEGINNING " name {yang-version 1.1;namespace urn:x;prefix \"x\";"
+#define SCHEMA_BEGINNING2 " name {namespace urn:x;prefix \"x\";"
+#define TEST_NODE(NODETYPE, INPUT, NAME) \
+        str = SCHEMA_BEGINNING INPUT; \
+        assert_int_equal(LY_SUCCESS, parse_module(&ctx, &str, mod)); \
+        assert_non_null(mod->data); \
+        assert_int_equal(NODETYPE, mod->data->nodetype); \
+        assert_string_equal(NAME, mod->data->name); \
+        mod = mod_renew(&ctx);
+#define TEST_GENERIC(INPUT, TARGET, TEST) \
+        str = SCHEMA_BEGINNING INPUT; \
+        assert_int_equal(LY_SUCCESS, parse_module(&ctx, &str, mod)); \
+        assert_non_null(TARGET); \
+        TEST; \
+        mod = mod_renew(&ctx);
+#define TEST_DUP(MEMBER, VALUE1, VALUE2, LINE) \
+        TEST_DUP_GENERIC(SCHEMA_BEGINNING, MEMBER, VALUE1, VALUE2, \
+                         parse_module, mod, LINE, mod = mod_renew(&ctx))
+
+    /* duplicated namespace, prefix */
+    TEST_DUP("namespace", "y", "z", "1");
+    TEST_DUP("prefix", "y", "z", "1");
+    TEST_DUP("contact", "a", "b", "1");
+    TEST_DUP("description", "a", "b", "1");
+    TEST_DUP("organization", "a", "b", "1");
+    TEST_DUP("reference", "a", "b", "1");
+
+    /* not allowed in module (submodule-specific) */
+    str = SCHEMA_BEGINNING "belongs-to master {prefix m;}}";
+    assert_int_equal(LY_EVALID, parse_module(&ctx, &str, mod));
+    logbuf_assert("Invalid keyword \"belongs-to\" as a child of \"module\". Line number 1.");
+    mod = mod_renew(&ctx);
+
+    /* anydata */
+    TEST_NODE(LYS_ANYDATA, "anydata test;}", "test");
+    /* anyxml */
+    TEST_NODE(LYS_ANYXML, "anyxml test;}", "test");
+    /* augment */
+    TEST_GENERIC("augment /somepath;}", mod->augments,
+                 assert_string_equal("/somepath", mod->augments[0].nodeid));
+    /* choice */
+    TEST_NODE(LYS_CHOICE, "choice test;}", "test");
+    /* contact 0..1 */
+    TEST_GENERIC("contact \"firstname\" + \n\t\" surname\";}", mod->mod->contact,
+                 assert_string_equal("firstname surname", mod->mod->contact));
+    /* container */
+    TEST_NODE(LYS_CONTAINER, "container test;}", "test");
+    /* description 0..1 */
+    TEST_GENERIC("description \'some description\';}", mod->mod->dsc,
+                 assert_string_equal("some description", mod->mod->dsc));
+    /* deviation */
+    TEST_GENERIC("deviation /somepath {deviate not-supported;}}", mod->deviations,
+                 assert_string_equal("/somepath", mod->deviations[0].nodeid));
+    /* extension */
+    TEST_GENERIC("extension test;}", mod->extensions,
+                 assert_string_equal("test", mod->extensions[0].name));
+    /* feature */
+    TEST_GENERIC("feature test;}", mod->features,
+                 assert_string_equal("test", mod->features[0].name));
+    /* grouping */
+    TEST_GENERIC("grouping grp;}", mod->groupings,
+                 assert_string_equal("grp", mod->groupings[0].name));
+    /* identity */
+    TEST_GENERIC("identity test;}", mod->identities,
+                 assert_string_equal("test", mod->identities[0].name));
+    /* import */
+    ly_ctx_set_module_imp_clb(ctx.ctx, test_imp_clb, "module zzz { namespace urn:zzz; prefix z;}");
+    TEST_GENERIC("import zzz {prefix z;}}", mod->imports,
+                 assert_string_equal("zzz", mod->imports[0].name));
+
+    /* import - prefix collision */
+    str = SCHEMA_BEGINNING "import zzz {prefix x;}}";
+    assert_int_equal(LY_EVALID, parse_module(&ctx, &str, mod));
+    logbuf_assert("Prefix \"x\" already used as module prefix. Line number 2.");
+    mod = mod_renew(&ctx);
+    str = SCHEMA_BEGINNING "import zzz {prefix y;}import zzz {prefix y;}}";
+    assert_int_equal(LY_EVALID, parse_module(&ctx, &str, mod));
+    logbuf_assert("Prefix \"y\" already used to import \"zzz\" module. Line number 2.");
+    mod = mod_renew(&ctx);
+    str = "module" SCHEMA_BEGINNING "import zzz {prefix y;}import zzz {prefix z;}}";
+    assert_null(lys_parse_mem(ctx.ctx, str, LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, ly_errcode(ctx.ctx));
+    logbuf_assert("Single revision of the module \"zzz\" referred twice.");
+
+    /* include */
+    store = 1;
+    ly_ctx_set_module_imp_clb(ctx.ctx, test_imp_clb, "module xxx { namespace urn:xxx; prefix x;}");
+    str = "module" SCHEMA_BEGINNING "include xxx;}";
+    assert_null(lys_parse_mem(ctx.ctx, str, LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, ly_errcode(ctx.ctx));
+    logbuf_assert("Input data contains module in situation when a submodule is expected.");
+    store = -1;
+
+    store = 1;
+    ly_ctx_set_module_imp_clb(ctx.ctx, test_imp_clb, "submodule xxx {belongs-to wrong-name {prefix w;}}");
+    str = "module" SCHEMA_BEGINNING "include xxx;}";
+    assert_null(lys_parse_mem(ctx.ctx, str, LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, ly_errcode(ctx.ctx));
+    logbuf_assert("Included \"xxx\" submodule from \"name\" belongs-to a different module \"wrong-name\".");
+    store = -1;
+
+    ly_ctx_set_module_imp_clb(ctx.ctx, test_imp_clb, "submodule xxx {belongs-to name {prefix x;}}");
+    TEST_GENERIC("include xxx;}", mod->includes,
+                 assert_string_equal("xxx", mod->includes[0].name));
+
+    /* leaf */
+    TEST_NODE(LYS_LEAF, "leaf test {type string;}}", "test");
+    /* leaf-list */
+    TEST_NODE(LYS_LEAFLIST, "leaf-list test {type string;}}", "test");
+    /* list */
+    TEST_NODE(LYS_LIST, "list test {key a;leaf a {type string;}}}", "test");
+    /* notification */
+    TEST_GENERIC("notification test;}", mod->notifs,
+                 assert_string_equal("test", mod->notifs[0].name));
+    /* organization 0..1 */
+    TEST_GENERIC("organization \"CESNET a.l.e.\";}", mod->mod->org,
+                 assert_string_equal("CESNET a.l.e.", mod->mod->org));
+    /* reference 0..1 */
+    TEST_GENERIC("reference RFC7950;}", mod->mod->ref,
+                 assert_string_equal("RFC7950", mod->mod->ref));
+    /* revision */
+    TEST_GENERIC("revision 2018-10-12;}", mod->revs,
+                 assert_string_equal("2018-10-12", mod->revs[0].date));
+    /* rpc */
+    TEST_GENERIC("rpc test;}", mod->rpcs,
+                 assert_string_equal("test", mod->rpcs[0].name));
+    /* typedef */
+    TEST_GENERIC("typedef test{type string;}}", mod->typedefs,
+                 assert_string_equal("test", mod->typedefs[0].name));
+    /* uses */
+    TEST_NODE(LYS_USES, "uses test;}", "test");
+    /* yang-version */
+    str = SCHEMA_BEGINNING2 "\n\tyang-version 10;}";
+    assert_int_equal(LY_EVALID, parse_module(&ctx, &str, mod));
+    logbuf_assert("Invalid value \"10\" of \"yang-version\". Line number 3.");
+    mod = mod_renew(&ctx);
+    str = SCHEMA_BEGINNING2 "yang-version 1.0;yang-version 1.1;}";
+    assert_int_equal(LY_EVALID, parse_module(&ctx, &str, mod));
+    logbuf_assert("Duplicate keyword \"yang-version\". Line number 3.");
+    mod = mod_renew(&ctx);
+    str = SCHEMA_BEGINNING2 "yang-version 1.0;}";
+    assert_int_equal(LY_SUCCESS, parse_module(&ctx, &str, mod));
+    assert_int_equal(1, mod->mod->version);
+    mod = mod_renew(&ctx);
+    str = SCHEMA_BEGINNING2 "yang-version \"1.1\";}";
+    assert_int_equal(LY_SUCCESS, parse_module(&ctx, &str, mod));
+    assert_int_equal(2, mod->mod->version);
+    mod = mod_renew(&ctx);
+
+    struct lys_yang_parser_ctx *ctx_p = NULL;
+    str = "module " SCHEMA_BEGINNING "} module q {namespace urn:q;prefixq;}";
+    m = mod->mod;
+    free(mod);
+    m->parsed = NULL;
+    assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, str, m));
+    logbuf_assert("Trailing garbage \"module q {names...\" after module, expected end-of-input. Line number 1.");
+    yang_parser_ctx_free(ctx_p);
+    mod = mod_renew(&ctx);
+
+    str = "prefix " SCHEMA_BEGINNING "}";
+    m = mod->mod;
+    free(mod);
+    m->parsed = NULL;
+    assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, str, m));
+    yang_parser_ctx_free(ctx_p);
+    logbuf_assert("Invalid keyword \"prefix\", expected \"module\" or \"submodule\". Line number 1.");
+    mod = mod_renew(&ctx);
+
+    str = "module " SCHEMA_BEGINNING "}";
+    str = "module " SCHEMA_BEGINNING "leaf enum {type enumeration {enum seven { position 7;}}}}";
+    m = mod->mod;
+    free(mod);
+    m->parsed = NULL;
+    assert_int_equal(LY_EVALID, yang_parse_module(&ctx_p, str, m));
+    yang_parser_ctx_free(ctx_p);
+    logbuf_assert("Invalid keyword \"position\" as a child of \"enum\". Line number 1.");
+    mod = mod_renew(&ctx);
+
+    /* extensions */
+    TEST_GENERIC("prefix:test;}", mod->exts,
+                 assert_string_equal("prefix:test", mod->exts[0].name);
+                 assert_int_equal(LYEXT_SUBSTMT_SELF, mod->exts[0].insubstmt));
+    mod = mod_renew(&ctx);
+
+    /* invalid substatement */
+    str = SCHEMA_BEGINNING "must false;}";
+    assert_int_equal(LY_EVALID, parse_module(&ctx, &str, mod));
+    logbuf_assert("Invalid keyword \"must\" as a child of \"module\". Line number 3.");
+    mod = mod_renew(&ctx);
+
+    /* submodule */
+    submod = submod_renew(&ctx, submod);
+
+    /* missing mandatory substatements */
+    str = " subname {}";
+    lydict_remove(ctx.ctx, submod->name);
+    assert_int_equal(LY_EVALID, parse_submodule(&ctx, &str, submod));
+    assert_string_equal("subname", submod->name);
+    logbuf_assert("Missing mandatory keyword \"belongs-to\" as a child of \"submodule\". Line number 3.");
+    submod = submod_renew(&ctx, submod);
+
+    str = " subname {belongs-to name {prefix x;}}";
+    lydict_remove(ctx.ctx, submod->name);
+    assert_int_equal(LY_SUCCESS, parse_submodule(&ctx, &str, submod));
+    assert_string_equal("name", submod->belongsto);
+    submod = submod_renew(&ctx, submod);
+
+#undef SCHEMA_BEGINNING
+#define SCHEMA_BEGINNING " subname {belongs-to name {prefix x;}"
+
+    /* duplicated namespace, prefix */
+    str = " subname {belongs-to name {prefix x;}belongs-to module1;belongs-to module2;} ...";
+    assert_int_equal(LY_EVALID, parse_submodule(&ctx, &str, submod)); \
+    logbuf_assert("Duplicate keyword \"belongs-to\". Line number 3."); \
+    submod = submod_renew(&ctx, submod);
+
+    /* not allowed in submodule (module-specific) */
+    str = SCHEMA_BEGINNING "namespace \"urn:z\";}";
+    assert_int_equal(LY_EVALID, parse_submodule(&ctx, &str, submod));
+    logbuf_assert("Invalid keyword \"namespace\" as a child of \"submodule\". Line number 3.");
+    submod = submod_renew(&ctx, submod);
+    str = SCHEMA_BEGINNING "prefix m;}}";
+    assert_int_equal(LY_EVALID, parse_submodule(&ctx, &str, submod));
+    logbuf_assert("Invalid keyword \"prefix\" as a child of \"submodule\". Line number 3.");
+    submod = submod_renew(&ctx, submod);
+
+    str = "submodule " SCHEMA_BEGINNING "} module q {namespace urn:q;prefixq;}";
+    lysp_submodule_free(ctx.ctx, submod);
+    submod = NULL;
+    assert_int_equal(LY_EVALID, yang_parse_submodule(&ctx_p, ctx.ctx, (struct lys_parser_ctx *)&ctx, str, &submod));
+    yang_parser_ctx_free(ctx_p);
+    logbuf_assert("Trailing garbage \"module q {names...\" after submodule, expected end-of-input. Line number 1.");
+
+    str = "prefix " SCHEMA_BEGINNING "}";
+    assert_int_equal(LY_EVALID, yang_parse_submodule(&ctx_p, ctx.ctx, (struct lys_parser_ctx *)&ctx, str, &submod));
+    yang_parser_ctx_free(ctx_p);
+    logbuf_assert("Invalid keyword \"prefix\", expected \"module\" or \"submodule\". Line number 1.");
+    submod = submod_renew(&ctx, submod);
+
+#undef TEST_GENERIC
+#undef TEST_NODE
+#undef TEST_DUP
+#undef SCHEMA_BEGINNING
+
+    lysp_module_free(mod);
+    lysp_submodule_free(ctx.ctx, submod);
+    ly_ctx_destroy(ctx.ctx, NULL);
+
+    *state = NULL;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+static void
+test_deviation(void **state)
+{
+    (void) state; /* unused */
+
+    struct lys_yang_parser_ctx ctx;
+    struct lysp_deviation *d = 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 {deviate not-supported;", MEMBER, VALUE1, VALUE2, parse_deviation, \
+                     &d, "1", FREE_ARRAY(ctx.ctx, d, lysp_deviation_free); d = NULL)
+
+    TEST_DUP("description", "a", "b");
+    TEST_DUP("reference", "a", "b");
+
+    /* full content */
+    str = " test {deviate not-supported;description text;reference \'another text\';prefix:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_deviation(&ctx, &str, &d));
+    assert_non_null(d);
+    assert_string_equal(" ...", str);
+    FREE_ARRAY(ctx.ctx, d, lysp_deviation_free);
+    d = NULL;
+
+    /* missing mandatory substatement */
+    str = " test {description text;}";
+    assert_int_equal(LY_EVALID, parse_deviation(&ctx, &str, &d));
+    logbuf_assert("Missing mandatory keyword \"deviate\" as a child of \"deviation\". Line number 1.");
+    FREE_ARRAY(ctx.ctx, d, lysp_deviation_free);
+    d = NULL;
+
+    /* invalid substatement */
+    str = " test {deviate not-supported; status obsolete;}";
+    assert_int_equal(LY_EVALID, parse_deviation(&ctx, &str, &d));
+    logbuf_assert("Invalid keyword \"status\" as a child of \"deviation\". Line number 1.");
+    FREE_ARRAY(ctx.ctx, d, lysp_deviation_free);
+    d = NULL;
+
+#undef TEST_DUP
+
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_deviate(void **state)
+{
+    (void) state; /* unused */
+
+    struct lys_yang_parser_ctx ctx;
+    struct lysp_deviate *d = 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(TYPE, MEMBER, VALUE1, VALUE2) \
+    TEST_DUP_GENERIC(TYPE" {", MEMBER, VALUE1, VALUE2, parse_deviate, \
+                     &d, "1", lysp_deviate_free(ctx.ctx, d); free(d); d = NULL)
+
+    TEST_DUP("add", "config", "true", "false");
+    TEST_DUP("replace", "default", "int8", "uint8");
+    TEST_DUP("add", "mandatory", "true", "false");
+    TEST_DUP("add", "max-elements", "1", "2");
+    TEST_DUP("add", "min-elements", "1", "2");
+    TEST_DUP("replace", "type", "int8", "uint8");
+    TEST_DUP("add", "units", "kilometers", "miles");
+
+    /* full contents */
+    str = " not-supported {prefix:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_deviate(&ctx, &str, &d));
+    assert_non_null(d);
+    assert_string_equal(" ...", str);
+    lysp_deviate_free(ctx.ctx, d); free(d); d = NULL;
+    str = " add {units meters; must 1; must 2; unique x; unique y; default a; default b; config true; mandatory true; min-elements 1; max-elements 2; prefix:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_deviate(&ctx, &str, &d));
+    assert_non_null(d);
+    assert_string_equal(" ...", str);
+    lysp_deviate_free(ctx.ctx, d); free(d); d = NULL;
+    str = " delete {units meters; must 1; must 2; unique x; unique y; default a; default b; prefix:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_deviate(&ctx, &str, &d));
+    assert_non_null(d);
+    assert_string_equal(" ...", str);
+    lysp_deviate_free(ctx.ctx, d); free(d); d = NULL;
+    str = " replace {type string; units meters; default a; config true; mandatory true; min-elements 1; max-elements 2; prefix:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_deviate(&ctx, &str, &d));
+    assert_non_null(d);
+    assert_string_equal(" ...", str);
+    lysp_deviate_free(ctx.ctx, d); free(d); d = NULL;
+
+    /* invalid substatements */
+#define TEST_NOT_SUP(DEV, STMT, VALUE) \
+    str = " "DEV" {"STMT" "VALUE";}..."; \
+    assert_int_equal(LY_EVALID, parse_deviate(&ctx, &str, &d)); \
+    logbuf_assert("Deviate \""DEV"\" does not support keyword \""STMT"\". Line number 1."); \
+    lysp_deviate_free(ctx.ctx, d); free(d); d = NULL
+
+    TEST_NOT_SUP("not-supported", "units", "meters");
+    TEST_NOT_SUP("not-supported", "must", "1");
+    TEST_NOT_SUP("not-supported", "unique", "x");
+    TEST_NOT_SUP("not-supported", "default", "a");
+    TEST_NOT_SUP("not-supported", "config", "true");
+    TEST_NOT_SUP("not-supported", "mandatory", "true");
+    TEST_NOT_SUP("not-supported", "min-elements", "1");
+    TEST_NOT_SUP("not-supported", "max-elements", "2");
+    TEST_NOT_SUP("not-supported", "type", "string");
+    TEST_NOT_SUP("add", "type", "string");
+    TEST_NOT_SUP("delete", "config", "true");
+    TEST_NOT_SUP("delete", "mandatory", "true");
+    TEST_NOT_SUP("delete", "min-elements", "1");
+    TEST_NOT_SUP("delete", "max-elements", "2");
+    TEST_NOT_SUP("delete", "type", "string");
+    TEST_NOT_SUP("replace", "must", "1");
+    TEST_NOT_SUP("replace", "unique", "a");
+
+    str = " nonsence; ...";
+    assert_int_equal(LY_EVALID, parse_deviate(&ctx, &str, &d));
+    logbuf_assert("Invalid value \"nonsence\" of \"deviate\". Line number 1.");
+    assert_null(d);
+
+#undef TEST_NOT_SUP
+#undef TEST_DUP
+
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_container(void **state)
+{
+    (void) state; /* unused */
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_node_container *c = 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.mod_version = 2; /* simulate YANG 1.1 */
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "cont {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_container(&ctx, &str, NULL, (struct lysp_node**)&c)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    lysp_node_free(ctx.ctx, (struct lysp_node*)c); c = NULL;
+
+    TEST_DUP("config", "true", "false");
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("presence", "true", "false");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+    TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+    /* full content */
+    str = "cont {action x;anydata any;anyxml anyxml; choice ch;config false;container c;description test;grouping g;if-feature f; leaf l {type string;}"
+          "leaf-list ll {type string;} list li;must 'expr';notification not; presence true; reference test;status current;typedef t {type int8;}uses g;when true;m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_container(&ctx, &str, NULL, (struct lysp_node**)&c));
+    assert_non_null(c);
+    assert_int_equal(LYS_CONTAINER, c->nodetype);
+    assert_string_equal("cont", c->name);
+    assert_non_null(c->actions);
+    assert_non_null(c->child);
+    assert_string_equal("test", c->dsc);
+    assert_non_null(c->exts);
+    assert_non_null(c->groupings);
+    assert_non_null(c->iffeatures);
+    assert_non_null(c->musts);
+    assert_non_null(c->notifs);
+    assert_string_equal("true", c->presence);
+    assert_string_equal("test", c->ref);
+    assert_non_null(c->typedefs);
+    assert_non_null(c->when);
+    assert_null(c->parent);
+    assert_null(c->next);
+    assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR, c->flags);
+    ly_set_erase(&ctx.tpdfs_nodes, NULL);
+    lysp_node_free(ctx.ctx, (struct lysp_node*)c); c = NULL;
+
+    /* invalid */
+    str = " cont {augment /root;} ...";
+    assert_int_equal(LY_EVALID, parse_container(&ctx, &str, NULL, (struct lysp_node**)&c));
+    logbuf_assert("Invalid keyword \"augment\" as a child of \"container\". Line number 1.");
+    lysp_node_free(ctx.ctx, (struct lysp_node*)c); c = NULL;
+    str = " cont {nonsence true;} ...";
+    assert_int_equal(LY_EVALID, parse_container(&ctx, &str, NULL, (struct lysp_node**)&c));
+    logbuf_assert("Invalid character sequence \"nonsence\", expected a keyword. Line number 1.");
+    lysp_node_free(ctx.ctx, (struct lysp_node*)c); c = NULL;
+
+    ctx.mod_version = 1; /* simulate YANG 1.0 */
+    str = " cont {action x;} ...";
+    assert_int_equal(LY_EVALID, parse_container(&ctx, &str, NULL, (struct lysp_node**)&c));
+    logbuf_assert("Invalid keyword \"action\" as a child of \"container\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+    lysp_node_free(ctx.ctx, (struct lysp_node*)c); c = NULL;
+
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_leaf(void **state)
+{
+    *state = test_leaf;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_node_leaf *l = 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.mod->version = 2; /* simulate YANG 1.1 */
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_leaf(&ctx, &str, NULL, (struct lysp_node**)&l)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+    TEST_DUP("config", "true", "false");
+    TEST_DUP("default", "x", "y");
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("mandatory", "true", "false");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+    TEST_DUP("type", "int8", "uint8");
+    TEST_DUP("units", "text1", "text2");
+    TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+    /* full content - without mandatory which is mutual exclusive with default */
+    str = "l {config false;default \"xxx\";description test;if-feature f;"
+          "must 'expr';reference test;status current;type string; units yyy;when true;m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_leaf(&ctx, &str, NULL, (struct lysp_node**)&l));
+    assert_non_null(l);
+    assert_int_equal(LYS_LEAF, l->nodetype);
+    assert_string_equal("l", l->name);
+    assert_string_equal("test", l->dsc);
+    assert_string_equal("xxx", l->dflt);
+    assert_string_equal("yyy", l->units);
+    assert_string_equal("string", l->type.name);
+    assert_non_null(l->exts);
+    assert_non_null(l->iffeatures);
+    assert_non_null(l->musts);
+    assert_string_equal("test", l->ref);
+    assert_non_null(l->when);
+    assert_null(l->parent);
+    assert_null(l->next);
+    assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR, l->flags);
+    lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+    /* full content - now with mandatory */
+    str = "l {mandatory true; type string;} ...";
+    assert_int_equal(LY_SUCCESS, parse_leaf(&ctx, &str, NULL, (struct lysp_node**)&l));
+    assert_non_null(l);
+    assert_int_equal(LYS_LEAF, l->nodetype);
+    assert_string_equal("l", l->name);
+    assert_string_equal("string", l->type.name);
+    assert_int_equal(LYS_MAND_TRUE, l->flags);
+    lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+    /* invalid */
+    str = " l {mandatory true; default xx; type string;} ...";
+    assert_int_equal(LY_EVALID, parse_leaf(&ctx, &str, NULL, (struct lysp_node**)&l));
+    logbuf_assert("Invalid combination of keywords \"mandatory\" and \"default\" as substatements of \"leaf\". Line number 1.");
+    lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+    str = " l {description \"missing type\";} ...";
+    assert_int_equal(LY_EVALID, parse_leaf(&ctx, &str, NULL, (struct lysp_node**)&l));
+    logbuf_assert("Missing mandatory keyword \"type\" as a child of \"leaf\". Line number 1.");
+    lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_leaflist(void **state)
+{
+    *state = test_leaf;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_node_leaflist *ll = 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.mod_version = 2; /* simulate YANG 1.1 */
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "ll {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+    TEST_DUP("config", "true", "false");
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("max-elements", "10", "20");
+    TEST_DUP("min-elements", "10", "20");
+    TEST_DUP("ordered-by", "user", "system");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+    TEST_DUP("type", "int8", "uint8");
+    TEST_DUP("units", "text1", "text2");
+    TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+    /* full content - without min-elements which is mutual exclusive with default */
+    str = "ll {config false;default \"xxx\"; default \"yyy\";description test;if-feature f;"
+          "max-elements 10;must 'expr';ordered-by user;reference test;"
+          "status current;type string; units zzz;when true;m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll));
+    assert_non_null(ll);
+    assert_int_equal(LYS_LEAFLIST, ll->nodetype);
+    assert_string_equal("ll", ll->name);
+    assert_string_equal("test", ll->dsc);
+    assert_non_null(ll->dflts);
+    assert_int_equal(2, LY_ARRAY_SIZE(ll->dflts));
+    assert_string_equal("xxx", ll->dflts[0]);
+    assert_string_equal("yyy", ll->dflts[1]);
+    assert_string_equal("zzz", ll->units);
+    assert_int_equal(10, ll->max);
+    assert_int_equal(0, ll->min);
+    assert_string_equal("string", ll->type.name);
+    assert_non_null(ll->exts);
+    assert_non_null(ll->iffeatures);
+    assert_non_null(ll->musts);
+    assert_string_equal("test", ll->ref);
+    assert_non_null(ll->when);
+    assert_null(ll->parent);
+    assert_null(ll->next);
+    assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_USER | LYS_SET_MAX, ll->flags);
+    lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+    /* full content - now with min-elements */
+    str = "ll {min-elements 10; type string;} ...";
+    assert_int_equal(LY_SUCCESS, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll));
+    assert_non_null(ll);
+    assert_int_equal(LYS_LEAFLIST, ll->nodetype);
+    assert_string_equal("ll", ll->name);
+    assert_string_equal("string", ll->type.name);
+    assert_int_equal(0, ll->max);
+    assert_int_equal(10, ll->min);
+    assert_int_equal(LYS_SET_MIN, ll->flags);
+    lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+    /* invalid */
+    str = " ll {min-elements 1; default xx; type string;} ...";
+    assert_int_equal(LY_EVALID, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll));
+    logbuf_assert("Invalid combination of keywords \"min-elements\" and \"default\" as substatements of \"leaf-list\". Line number 1.");
+    lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+    str = " ll {description \"missing type\";} ...";
+    assert_int_equal(LY_EVALID, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll));
+    logbuf_assert("Missing mandatory keyword \"type\" as a child of \"leaf-list\". Line number 1.");
+    lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+    str = " ll {type string; min-elements 10; max-elements 1;} ..."; /* invalid combination of min/max */
+    assert_int_equal(LY_EVALID, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll));
+    logbuf_assert("Invalid combination of min-elements and max-elements: min value 10 is bigger than the max value 1. Line number 1.");
+    lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+    ctx.mod_version = 1; /* simulate YANG 1.0 - default statement is not allowed */
+    str = " ll {default xx; type string;} ...";
+    assert_int_equal(LY_EVALID, parse_leaflist(&ctx, &str, NULL, (struct lysp_node**)&ll));
+    logbuf_assert("Invalid keyword \"default\" as a child of \"leaf-list\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+    lysp_node_free(ctx.ctx, (struct lysp_node*)ll); ll = NULL;
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_list(void **state)
+{
+    *state = test_list;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_node_list *l = 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.mod_version = 2; /* simulate YANG 1.1 */
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_list(&ctx, &str, NULL, (struct lysp_node**)&l)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+    TEST_DUP("config", "true", "false");
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("key", "one", "two");
+    TEST_DUP("max-elements", "10", "20");
+    TEST_DUP("min-elements", "10", "20");
+    TEST_DUP("ordered-by", "user", "system");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+    TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+    /* full content */
+    str = "l {action x;anydata any;anyxml anyxml; choice ch;config false;container c;description test;grouping g;if-feature f; key l; leaf l {type string;}"
+          "leaf-list ll {type string;} list li;max-elements 10; min-elements 1;must 'expr';notification not; ordered-by system; reference test;"
+          "status current;typedef t {type int8;}unique xxx;unique yyy;uses g;when true;m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_list(&ctx, &str, NULL, (struct lysp_node**)&l));
+    assert_non_null(l);
+    assert_int_equal(LYS_LIST, l->nodetype);
+    assert_string_equal("l", l->name);
+    assert_string_equal("test", l->dsc);
+    assert_string_equal("l", l->key);
+    assert_non_null(l->uniques);
+    assert_int_equal(2, LY_ARRAY_SIZE(l->uniques));
+    assert_string_equal("xxx", l->uniques[0]);
+    assert_string_equal("yyy", l->uniques[1]);
+    assert_int_equal(10, l->max);
+    assert_int_equal(1, l->min);
+    assert_non_null(l->exts);
+    assert_non_null(l->iffeatures);
+    assert_non_null(l->musts);
+    assert_string_equal("test", l->ref);
+    assert_non_null(l->when);
+    assert_null(l->parent);
+    assert_null(l->next);
+    assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM | LYS_SET_MAX | LYS_SET_MIN, l->flags);
+    ly_set_erase(&ctx.tpdfs_nodes, NULL);
+    lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+    /* invalid content */
+    ctx.mod_version = 1; /* simulate YANG 1.0 */
+    str = "l {action x;} ...";
+    assert_int_equal(LY_EVALID, parse_list(&ctx, &str, NULL, (struct lysp_node**)&l));
+    logbuf_assert("Invalid keyword \"action\" as a child of \"list\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+    lysp_node_free(ctx.ctx, (struct lysp_node*)l); l = NULL;
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_choice(void **state)
+{
+    *state = test_choice;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_node_choice *ch = 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.mod_version = 2; /* simulate YANG 1.1 */
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "ch {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_choice(&ctx, &str, NULL, (struct lysp_node**)&ch)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    lysp_node_free(ctx.ctx, (struct lysp_node*)ch); ch = NULL;
+
+    TEST_DUP("config", "true", "false");
+    TEST_DUP("default", "a", "b");
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("mandatory", "true", "false");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+    TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+    /* full content - without default due to a collision with mandatory */
+    str = "ch {anydata any;anyxml anyxml; case c;choice ch;config false;container c;description test;if-feature f;leaf l {type string;}"
+          "leaf-list ll {type string;} list li;mandatory true;reference test;status current;when true;m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_choice(&ctx, &str, NULL, (struct lysp_node**)&ch));
+    assert_non_null(ch);
+    assert_int_equal(LYS_CHOICE, ch->nodetype);
+    assert_string_equal("ch", ch->name);
+    assert_string_equal("test", ch->dsc);
+    assert_non_null(ch->exts);
+    assert_non_null(ch->iffeatures);
+    assert_string_equal("test", ch->ref);
+    assert_non_null(ch->when);
+    assert_null(ch->parent);
+    assert_null(ch->next);
+    assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_MAND_TRUE, ch->flags);
+    lysp_node_free(ctx.ctx, (struct lysp_node*)ch); ch = NULL;
+
+    /* full content - the default missing from the previous node */
+    str = "ch {default c;case c;} ...";
+    assert_int_equal(LY_SUCCESS, parse_choice(&ctx, &str, NULL, (struct lysp_node**)&ch));
+    assert_non_null(ch);
+    assert_int_equal(LYS_CHOICE, ch->nodetype);
+    assert_string_equal("ch", ch->name);
+    assert_string_equal("c", ch->dflt);
+    assert_int_equal(0, ch->flags);
+    lysp_node_free(ctx.ctx, (struct lysp_node*)ch); ch = NULL;
+
+    /* invalid content */
+    str = "ch {mandatory true; default c1; case c1 {leaf x{type string;}}} ...";
+    assert_int_equal(LY_EVALID, parse_choice(&ctx, &str, NULL, (struct lysp_node**)&ch));
+    logbuf_assert("Invalid combination of keywords \"mandatory\" and \"default\" as substatements of \"choice\". Line number 1.");
+    lysp_node_free(ctx.ctx, (struct lysp_node*)ch); ch = NULL;
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_case(void **state)
+{
+    *state = test_case;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_node_case *cs = 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.mod_version = 2; /* simulate YANG 1.1 */
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "cs {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_case(&ctx, &str, NULL, (struct lysp_node**)&cs)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    lysp_node_free(ctx.ctx, (struct lysp_node*)cs); cs = NULL;
+
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+    TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+    /* full content */
+    str = "cs {anydata any;anyxml anyxml; choice ch;container c;description test;if-feature f;leaf l {type string;}"
+          "leaf-list ll {type string;} list li;reference test;status current;uses grp;when true;m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_case(&ctx, &str, NULL, (struct lysp_node**)&cs));
+    assert_non_null(cs);
+    assert_int_equal(LYS_CASE, cs->nodetype);
+    assert_string_equal("cs", cs->name);
+    assert_string_equal("test", cs->dsc);
+    assert_non_null(cs->exts);
+    assert_non_null(cs->iffeatures);
+    assert_string_equal("test", cs->ref);
+    assert_non_null(cs->when);
+    assert_null(cs->parent);
+    assert_null(cs->next);
+    assert_int_equal(LYS_STATUS_CURR, cs->flags);
+    lysp_node_free(ctx.ctx, (struct lysp_node*)cs); cs = NULL;
+
+    /* invalid content */
+    str = "cs {config true} ...";
+    assert_int_equal(LY_EVALID, parse_case(&ctx, &str, NULL, (struct lysp_node**)&cs));
+    logbuf_assert("Invalid keyword \"config\" as a child of \"case\". Line number 1.");
+    lysp_node_free(ctx.ctx, (struct lysp_node*)cs); cs = NULL;
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_any(void **state, enum ly_stmt kw)
+{
+    *state = test_any;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_node_anydata *any = 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;
+    if (kw == LY_STMT_ANYDATA) {
+        ctx.mod_version = 2; /* simulate YANG 1.1 */
+    } else {
+        ctx.mod_version = 1; /* simulate YANG 1.0 */
+    }
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_any(&ctx, &str, kw, NULL, (struct lysp_node**)&any)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    lysp_node_free(ctx.ctx, (struct lysp_node*)any); any = NULL;
+
+    TEST_DUP("config", "true", "false");
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("mandatory", "true", "false");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+    TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+    /* full content */
+    str = "any {config true;description test;if-feature f;mandatory true;must 'expr';reference test;status current;when true;m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_any(&ctx, &str, kw, NULL, (struct lysp_node**)&any));
+    assert_non_null(any);
+    assert_int_equal(kw == LY_STMT_ANYDATA ? LYS_ANYDATA : LYS_ANYXML, any->nodetype);
+    assert_string_equal("any", any->name);
+    assert_string_equal("test", any->dsc);
+    assert_non_null(any->exts);
+    assert_non_null(any->iffeatures);
+    assert_non_null(any->musts);
+    assert_string_equal("test", any->ref);
+    assert_non_null(any->when);
+    assert_null(any->parent);
+    assert_null(any->next);
+    assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR | LYS_MAND_TRUE, any->flags);
+    lysp_node_free(ctx.ctx, (struct lysp_node*)any); any = NULL;
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_anydata(void **state)
+{
+    return test_any(state, LY_STMT_ANYDATA);
+}
+
+static void
+test_anyxml(void **state)
+{
+    return test_any(state, LY_STMT_ANYXML);
+}
+
+static void
+test_grouping(void **state)
+{
+    *state = test_grouping;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_grp *grp = 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.mod_version = 2; /* simulate YANG 1.1 */
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_grouping(&ctx, &str, NULL, &grp)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    FREE_ARRAY(ctx.ctx, grp, lysp_grp_free); grp = NULL;
+
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+#undef TEST_DUP
+
+    /* full content */
+    str = "grp {action x;anydata any;anyxml anyxml; choice ch;container c;description test;grouping g;leaf l {type string;}"
+          "leaf-list ll {type string;} list li;notification not;reference test;status current;typedef t {type int8;}uses g;m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_grouping(&ctx, &str, NULL, &grp));
+    assert_non_null(grp);
+    assert_int_equal(LYS_GROUPING, grp->nodetype);
+    assert_string_equal("grp", grp->name);
+    assert_string_equal("test", grp->dsc);
+    assert_non_null(grp->exts);
+    assert_string_equal("test", grp->ref);
+    assert_null(grp->parent);
+    assert_int_equal( LYS_STATUS_CURR, grp->flags);
+    ly_set_erase(&ctx.tpdfs_nodes, NULL);
+    FREE_ARRAY(ctx.ctx, grp, lysp_grp_free); grp = NULL;
+
+    /* invalid content */
+    str = "grp {config true} ...";
+    assert_int_equal(LY_EVALID, parse_grouping(&ctx, &str, NULL, &grp));
+    logbuf_assert("Invalid keyword \"config\" as a child of \"grouping\". Line number 1.");
+    FREE_ARRAY(ctx.ctx, grp, lysp_grp_free); grp = NULL;
+
+    str = "grp {must 'expr'} ...";
+    assert_int_equal(LY_EVALID, parse_grouping(&ctx, &str, NULL, &grp));
+    logbuf_assert("Invalid keyword \"must\" as a child of \"grouping\". Line number 1.");
+    FREE_ARRAY(ctx.ctx, grp, lysp_grp_free); grp = NULL;
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_action(void **state)
+{
+    *state = test_action;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_action *rpcs = NULL;
+    struct lysp_node_container *c = 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.mod_version = 2; /* simulate YANG 1.1 */
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "func {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_action(&ctx, &str, NULL, &rpcs)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    FREE_ARRAY(ctx.ctx, rpcs, lysp_action_free); rpcs = NULL;
+
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("input", "{leaf l1 {type empty;}} description a", "{leaf l2 {type empty;}} description a");
+    TEST_DUP("output", "{leaf l1 {type empty;}} description a", "{leaf l2 {type empty;}} description a");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+#undef TEST_DUP
+
+    /* full content */
+    str = "top;";
+    assert_int_equal(LY_SUCCESS, parse_container(&ctx, &str, NULL, (struct lysp_node**)&c));
+    str = "func {description test;grouping grp;if-feature f;reference test;status current;typedef mytype {type int8;} m:ext;"
+          "input {anydata a1; anyxml a2; choice ch; container c; grouping grp; leaf l {type int8;} leaf-list ll {type int8;}"
+          " list li; must 1; typedef mytypei {type int8;} uses grp; m:ext;}"
+          "output {anydata a1; anyxml a2; choice ch; container c; grouping grp; leaf l {type int8;} leaf-list ll {type int8;}"
+          " list li; must 1; typedef mytypeo {type int8;} uses grp; m:ext;}} ...";
+    assert_int_equal(LY_SUCCESS, parse_action(&ctx, &str, (struct lysp_node*)c, &rpcs));
+    assert_non_null(rpcs);
+    assert_int_equal(LYS_ACTION, rpcs->nodetype);
+    assert_string_equal("func", rpcs->name);
+    assert_string_equal("test", rpcs->dsc);
+    assert_non_null(rpcs->exts);
+    assert_non_null(rpcs->iffeatures);
+    assert_string_equal("test", rpcs->ref);
+    assert_non_null(rpcs->groupings);
+    assert_non_null(rpcs->typedefs);
+    assert_int_equal(LYS_STATUS_CURR, rpcs->flags);
+    /* input */
+    assert_int_equal(rpcs->input.nodetype, LYS_INPUT);
+    assert_non_null(rpcs->input.groupings);
+    assert_non_null(rpcs->input.exts);
+    assert_non_null(rpcs->input.musts);
+    assert_non_null(rpcs->input.typedefs);
+    assert_non_null(rpcs->input.data);
+    /* output */
+    assert_int_equal(rpcs->output.nodetype, LYS_OUTPUT);
+    assert_non_null(rpcs->output.groupings);
+    assert_non_null(rpcs->output.exts);
+    assert_non_null(rpcs->output.musts);
+    assert_non_null(rpcs->output.typedefs);
+    assert_non_null(rpcs->output.data);
+
+    ly_set_erase(&ctx.tpdfs_nodes, NULL);
+    FREE_ARRAY(ctx.ctx, rpcs, lysp_action_free); rpcs = NULL;
+
+    /* invalid content */
+    str = "func {config true} ...";
+    assert_int_equal(LY_EVALID, parse_action(&ctx, &str, NULL, &rpcs));
+    logbuf_assert("Invalid keyword \"config\" as a child of \"rpc\". Line number 1.");
+    FREE_ARRAY(ctx.ctx, rpcs, lysp_action_free); rpcs = NULL;
+
+    *state = NULL;
+    lysp_node_free(ctx.ctx, (struct lysp_node*)c);
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_notification(void **state)
+{
+    *state = test_notification;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_notif *notifs = NULL;
+    struct lysp_node_container *c = 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.mod_version = 2; /* simulate YANG 1.1 */
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "func {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_notif(&ctx, &str, NULL, &notifs)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    FREE_ARRAY(ctx.ctx, notifs, lysp_notif_free); notifs = NULL;
+
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+#undef TEST_DUP
+
+    /* full content */
+    str = "top;";
+    assert_int_equal(LY_SUCCESS, parse_container(&ctx, &str, NULL, (struct lysp_node**)&c));
+    str = "ntf {anydata a1; anyxml a2; choice ch; container c; description test; grouping grp; if-feature f; leaf l {type int8;}"
+          "leaf-list ll {type int8;} list li; must 1; reference test; status current; typedef mytype {type int8;} uses grp; m:ext;}";
+    assert_int_equal(LY_SUCCESS, parse_notif(&ctx, &str, (struct lysp_node*)c, &notifs));
+    assert_non_null(notifs);
+    assert_int_equal(LYS_NOTIF, notifs->nodetype);
+    assert_string_equal("ntf", notifs->name);
+    assert_string_equal("test", notifs->dsc);
+    assert_non_null(notifs->exts);
+    assert_non_null(notifs->iffeatures);
+    assert_string_equal("test", notifs->ref);
+    assert_non_null(notifs->groupings);
+    assert_non_null(notifs->typedefs);
+    assert_non_null(notifs->musts);
+    assert_non_null(notifs->data);
+    assert_int_equal(LYS_STATUS_CURR, notifs->flags);
+
+    ly_set_erase(&ctx.tpdfs_nodes, NULL);
+    FREE_ARRAY(ctx.ctx, notifs, lysp_notif_free); notifs = NULL;
+
+    /* invalid content */
+    str = "ntf {config true} ...";
+    assert_int_equal(LY_EVALID, parse_notif(&ctx, &str, NULL, &notifs));
+    logbuf_assert("Invalid keyword \"config\" as a child of \"notification\". Line number 1.");
+    FREE_ARRAY(ctx.ctx, notifs, lysp_notif_free); notifs = NULL;
+
+    *state = NULL;
+    lysp_node_free(ctx.ctx, (struct lysp_node*)c);
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_uses(void **state)
+{
+    *state = test_uses;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_node_uses *u = 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.mod_version = 2; /* simulate YANG 1.1 */
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_uses(&ctx, &str, NULL, (struct lysp_node**)&u)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    lysp_node_free(ctx.ctx, (struct lysp_node*)u); u = NULL;
+
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+    TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+    /* full content */
+    str = "grpref {augment some/node;description test;if-feature f;reference test;refine some/other/node;status current;when true;m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_uses(&ctx, &str, NULL, (struct lysp_node**)&u));
+    assert_non_null(u);
+    assert_int_equal(LYS_USES, u->nodetype);
+    assert_string_equal("grpref", u->name);
+    assert_string_equal("test", u->dsc);
+    assert_non_null(u->exts);
+    assert_non_null(u->iffeatures);
+    assert_string_equal("test", u->ref);
+    assert_non_null(u->augments);
+    assert_non_null(u->refines);
+    assert_non_null(u->when);
+    assert_null(u->parent);
+    assert_null(u->next);
+    assert_int_equal(LYS_STATUS_CURR, u->flags);
+    lysp_node_free(ctx.ctx, (struct lysp_node*)u); u = NULL;
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+
+static void
+test_augment(void **state)
+{
+    *state = test_augment;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_augment *a = 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.mod_version = 2; /* simulate YANG 1.1 */
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_augment(&ctx, &str, NULL, &a)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    FREE_ARRAY(ctx.ctx, a, lysp_augment_free); a = NULL;
+
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("reference", "1", "2");
+    TEST_DUP("status", "current", "obsolete");
+    TEST_DUP("when", "true", "false");
+#undef TEST_DUP
+
+    /* full content */
+    str = "/target/nodeid {action x; anydata any;anyxml anyxml; case cs; choice ch;container c;description test;if-feature f;leaf l {type string;}"
+          "leaf-list ll {type string;} list li;notification not;reference test;status current;uses g;when true;m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_augment(&ctx, &str, NULL, &a));
+    assert_non_null(a);
+    assert_int_equal(LYS_AUGMENT, a->nodetype);
+    assert_string_equal("/target/nodeid", a->nodeid);
+    assert_string_equal("test", a->dsc);
+    assert_non_null(a->exts);
+    assert_non_null(a->iffeatures);
+    assert_string_equal("test", a->ref);
+    assert_non_null(a->when);
+    assert_null(a->parent);
+    assert_int_equal(LYS_STATUS_CURR, a->flags);
+    FREE_ARRAY(ctx.ctx, a, lysp_augment_free); a = NULL;
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_when(void **state)
+{
+    *state = test_when;
+
+    struct lys_yang_parser_ctx ctx = {0};
+    struct lysp_when *w = 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.mod_version = 2; /* simulate YANG 1.1 */
+
+    /* invalid cardinality */
+#define TEST_DUP(MEMBER, VALUE1, VALUE2) \
+    str = "l {" MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, parse_when(&ctx, &str, &w)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number 1."); \
+    FREE_MEMBER(ctx.ctx, w, lysp_when_free); w = NULL;
+
+    TEST_DUP("description", "text1", "text2");
+    TEST_DUP("reference", "1", "2");
+#undef TEST_DUP
+
+    /* full content */
+    str = "expression {description test;reference test;m:ext;} ...";
+    assert_int_equal(LY_SUCCESS, parse_when(&ctx, &str, &w));
+    assert_non_null(w);
+    assert_string_equal("expression", w->cond);
+    assert_string_equal("test", w->dsc);
+    assert_string_equal("test", w->ref);
+    assert_non_null(w->exts);
+    FREE_MEMBER(ctx.ctx, w, lysp_when_free); w = NULL;
+
+    /* empty condition */
+    str = "\"\";";
+    assert_int_equal(LY_SUCCESS, parse_when(&ctx, &str, &w));
+    logbuf_assert("Empty argument of when statement does not make sense.");
+    assert_non_null(w);
+    assert_string_equal("", w->cond);
+    FREE_MEMBER(ctx.ctx, w, lysp_when_free); w = NULL;
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+static void
+test_value(void **state)
+{
+    *state = test_value;
+    struct lys_yang_parser_ctx ctx;
+
+    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;
+    int64_t val = 0;
+    uint16_t flags = 0;
+
+    const char *data = "-0;";
+    assert_int_equal(parse_type_enum_value_pos(&ctx, &data, LY_STMT_VALUE, &val, &flags, NULL), LY_SUCCESS);
+    assert_int_equal(val, 0);
+
+    data = "-0;";
+    flags = 0;
+    assert_int_equal(parse_type_enum_value_pos(&ctx, &data, LY_STMT_POSITION, &val, &flags, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"-0\" of \"position\". Line number 1.");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx.ctx, NULL);
+}
+
+int main(void)
+{
+    const struct CMUnitTest tests[] = {
+        cmocka_unit_test_setup(test_helpers, logger_setup),
+        cmocka_unit_test_setup(test_comments, logger_setup),
+        cmocka_unit_test_setup(test_arg, logger_setup),
+        cmocka_unit_test_setup(test_stmts, logger_setup),
+        cmocka_unit_test_setup_teardown(test_minmax, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_module, logger_setup, logger_teardown),
+        cmocka_unit_test_setup(test_deviation, logger_setup),
+        cmocka_unit_test_setup(test_deviate, logger_setup),
+        cmocka_unit_test_setup(test_container, logger_setup),
+        cmocka_unit_test_setup_teardown(test_leaf, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_leaflist, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_list, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_choice, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_case, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_anydata, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_anyxml, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_action, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_notification, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_grouping, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_uses, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_augment, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_when, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_value, logger_setup, logger_teardown),
+    };
+
+    return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/utests/schema/test_parser_yin.c b/tests/utests/schema/test_parser_yin.c
new file mode 100644
index 0000000..ea22333
--- /dev/null
+++ b/tests/utests/schema/test_parser_yin.c
@@ -0,0 +1,4384 @@
+/**
+ * @file test_parser_yin.c
+ * @author David Sedlák <xsedla1d@stud.fit.vutbr.cz>
+ * @brief unit tests for functions from parser_yin.c
+ *
+ * Copyright (c) 2015 - 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 <setjmp.h>
+#include <cmocka.h>
+
+#include <stdio.h>
+#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"
+
+/* prototypes of static functions */
+void lysp_ext_instance_free(struct ly_ctx *ctx, struct lysp_ext_instance *ext);
+void lysp_ext_free(struct ly_ctx *ctx, struct lysp_ext *ext);
+void lysp_when_free(struct ly_ctx *ctx, struct lysp_when *when);
+void lysp_type_free(struct ly_ctx *ctx, struct lysp_type *type);
+void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node);
+void lysp_tpdf_free(struct ly_ctx *ctx, struct lysp_tpdf *tpdf);
+void lysp_refine_free(struct ly_ctx *ctx, struct lysp_refine *ref);
+void lysp_revision_free(struct ly_ctx *ctx, struct lysp_revision *rev);
+void lysp_include_free(struct ly_ctx *ctx, struct lysp_include *include);
+void lysp_feature_free(struct ly_ctx *ctx, struct lysp_feature *feat);
+void lysp_ident_free(struct ly_ctx *ctx, struct lysp_ident *ident);
+void lysp_notif_free(struct ly_ctx *ctx, struct lysp_notif *notif);
+void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp);
+void lysp_action_inout_free(struct ly_ctx *ctx, struct lysp_action_inout *inout);
+void lysp_action_free(struct ly_ctx *ctx, struct lysp_action *action);
+void lysp_augment_free(struct ly_ctx *ctx, struct lysp_augment *augment);
+void lysp_deviate_free(struct ly_ctx *ctx, struct lysp_deviate *d);
+void lysp_deviation_free(struct ly_ctx *ctx, struct lysp_deviation *dev);
+void lysp_submodule_free(struct ly_ctx *ctx, struct lysp_submodule *submod);
+void lysp_import_free(struct ly_ctx *ctx, struct lysp_import *import);
+
+/* wrapping element used for mocking has nothing to do with real module structure */
+#define ELEMENT_WRAPPER_START "<status xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
+#define ELEMENT_WRAPPER_END "</status>"
+
+struct test_parser_yin_state {
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysp_module *lysp_mod;
+    struct lys_yin_parser_ctx *yin_ctx;
+    bool finished_correctly;
+};
+
+#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
+
+#if ENABLE_LOGGER_CHECKING
+#   define logbuf_assert(str) assert_string_equal(logbuf, str)
+#else
+#   define logbuf_assert(str)
+#endif
+
+#define TEST_DUP_GENERIC(PREFIX, MEMBER, VALUE1, VALUE2, FUNC, RESULT, LINE, CLEANUP) \
+    str = PREFIX MEMBER" "VALUE1";"MEMBER" "VALUE2";} ..."; \
+    assert_int_equal(LY_EVALID, FUNC(&ctx, &str, RESULT)); \
+    logbuf_assert("Duplicate keyword \""MEMBER"\". Line number "LINE"."); \
+    CLEANUP
+
+int
+setup_ly_ctx(void **state)
+{
+    struct test_parser_yin_state *st = NULL;
+
+    /* allocate state variable */
+    (*state) = st = calloc(1, sizeof(*st));
+    if (!st) {
+        fprintf(stderr, "Memmory allocation failed");
+        return EXIT_FAILURE;
+    }
+
+    /* create new libyang context */
+    ly_ctx_new(NULL, 0, &st->ctx);
+
+    return EXIT_SUCCESS;
+}
+
+int
+destroy_ly_ctx(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    ly_ctx_destroy(st->ctx, NULL);
+    free(st);
+
+    return EXIT_SUCCESS;
+}
+
+static int
+setup_f(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+
+#if ENABLE_LOGGER_CHECKING
+    /* setup logger */
+    ly_set_log_clb(logger, 1);
+#endif
+
+    /* allocate new module */
+    st->mod = calloc(1, sizeof(*st->mod));
+    st->mod->ctx = st->ctx;
+
+    /* allocate new parsed module */
+    st->lysp_mod = calloc(1, sizeof(*st->lysp_mod));
+    st->lysp_mod->mod = calloc(1, sizeof(*st->lysp_mod->mod));
+    st->lysp_mod->mod->ctx = st->ctx;
+
+    /* allocate parser context */
+    st->yin_ctx = calloc(1, sizeof(*st->yin_ctx));
+    st->yin_ctx->format = LYS_IN_YIN;
+
+    return EXIT_SUCCESS;
+}
+
+static int
+teardown_f(void **state)
+{
+    struct test_parser_yin_state *st = *(struct test_parser_yin_state **)state;
+    struct lys_module *temp;
+
+#if ENABLE_LOGGER_CHECKING
+    /* teardown logger */
+    if (!st->finished_correctly && logbuf[0] != '\0') {
+        fprintf(stderr, "%s\n", logbuf);
+    }
+#endif
+
+    temp = st->lysp_mod->mod;
+
+    lyxml_ctx_free(st->yin_ctx->xmlctx);
+    lys_module_free(st->mod, NULL);
+    lysp_module_free(st->lysp_mod);
+    lys_module_free(temp, NULL);
+    free(st->yin_ctx);
+
+    return EXIT_SUCCESS;
+}
+
+static struct test_parser_yin_state*
+reset_state(void **state)
+{
+    ((struct test_parser_yin_state *)*state)->finished_correctly = true;
+    logbuf[0] = '\0';
+    teardown_f(state);
+    setup_f(state);
+
+    return *state;
+}
+
+void
+logbuf_clean(void)
+{
+    logbuf[0] = '\0';
+}
+
+static int
+setup_logger(void **state)
+{
+    (void)state; /* unused */
+#if ENABLE_LOGGER_CHECKING
+    /* setup logger */
+    ly_set_log_clb(logger, 1);
+#endif
+
+    logbuf[0] = '\0';
+
+    return EXIT_SUCCESS;
+}
+
+static int
+teardown_logger(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+
+#if ENABLE_LOGGER_CHECKING
+    /* teardown logger */
+    if (!st->finished_correctly && logbuf[0] != '\0') {
+        fprintf(stderr, "%s\n", logbuf);
+    }
+#endif
+
+    return EXIT_SUCCESS;
+}
+
+static int
+setup_element_test(void **state)
+{
+    setup_logger(state);
+    struct test_parser_yin_state *st = *state;
+
+    st->yin_ctx = calloc(1, sizeof(*st->yin_ctx));
+    st->yin_ctx->format = LYS_IN_YIN;
+
+    return EXIT_SUCCESS;
+}
+
+static int
+teardown_element_test(void **state)
+{
+    struct test_parser_yin_state *st = *(struct test_parser_yin_state **)state;
+
+    lyxml_ctx_free(st->yin_ctx->xmlctx);
+    free(st->yin_ctx);
+
+    teardown_logger(state);
+
+    return EXIT_SUCCESS;
+}
+
+static void
+test_yin_match_keyword(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+
+    const char *prefix;
+    size_t prefix_len;
+    /* create mock yin namespace in xml context */
+    const char *data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" />";
+    lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
+    prefix = st->yin_ctx->xmlctx->prefix;
+    prefix_len = st->yin_ctx->xmlctx->prefix_len;
+
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "anydatax", strlen("anydatax"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_NONE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "asdasd", strlen("asdasd"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_NONE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "", 0, prefix, prefix_len, LY_STMT_NONE), LY_STMT_NONE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "anydata", strlen("anydata"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_ANYDATA);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "anyxml", strlen("anyxml"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_ANYXML);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "argument", strlen("argument"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_ARGUMENT);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "augment", strlen("augment"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_AUGMENT);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "base", strlen("base"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_BASE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "belongs-to", strlen("belongs-to"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_BELONGS_TO);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "bit", strlen("bit"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_BIT);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "case", strlen("case"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_CASE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "choice", strlen("choice"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_CHOICE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "config", strlen("config"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_CONFIG);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "contact", strlen("contact"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_CONTACT);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "container", strlen("container"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_CONTAINER);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "default", strlen("default"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_DEFAULT);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "description", strlen("description"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_DESCRIPTION);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "deviate", strlen("deviate"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_DEVIATE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "deviation", strlen("deviation"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_DEVIATION);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "enum", strlen("enum"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_ENUM);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "error-app-tag", strlen("error-app-tag"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_ERROR_APP_TAG);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "error-message", strlen("error-message"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_ERROR_MESSAGE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "extension", strlen("extension"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_EXTENSION);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "feature", strlen("feature"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_FEATURE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "fraction-digits", strlen("fraction-digits"), prefix,  prefix_len, LY_STMT_NONE), LY_STMT_FRACTION_DIGITS);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "grouping", strlen("grouping"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_GROUPING);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "identity", strlen("identity"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_IDENTITY);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "if-feature", strlen("if-feature"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_IF_FEATURE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "import", strlen("import"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_IMPORT);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "include", strlen("include"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_INCLUDE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "input", strlen("input"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_INPUT);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "key", strlen("key"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_KEY);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "leaf", strlen("leaf"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_LEAF);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "leaf-list", strlen("leaf-list"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_LEAF_LIST);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "length", strlen("length"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_LENGTH);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "list", strlen("list"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_LIST);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "mandatory", strlen("mandatory"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_MANDATORY);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "max-elements", strlen("max-elements"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_MAX_ELEMENTS);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "min-elements", strlen("min-elements"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_MIN_ELEMENTS);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "modifier", strlen("modifier"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_MODIFIER);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "module", strlen("module"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_MODULE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "must", strlen("must"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_MUST);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "namespace", strlen("namespace"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_NAMESPACE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "notification", strlen("notification"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_NOTIFICATION);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "ordered-by", strlen("ordered-by"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_ORDERED_BY);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "organization", strlen("organization"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_ORGANIZATION);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "output", strlen("output"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_OUTPUT);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "path", strlen("path"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_PATH);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "pattern", strlen("pattern"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_PATTERN);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "position", strlen("position"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_POSITION);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "prefix", strlen("prefix"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_PREFIX);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "presence", strlen("presence"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_PRESENCE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "range", strlen("range"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_RANGE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "reference", strlen("reference"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_REFERENCE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "refine", strlen("refine"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_REFINE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "require-instance", strlen("require-instance"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_REQUIRE_INSTANCE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "revision", strlen("revision"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_REVISION);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "revision-date", strlen("revision-date"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_REVISION_DATE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "rpc", strlen("rpc"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_RPC);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "status", strlen("status"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_STATUS);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "submodule", strlen("submodule"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_SUBMODULE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "type", strlen("type"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_TYPE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "typedef", strlen("typedef"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_TYPEDEF);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "unique", strlen("unique"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_UNIQUE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "units", strlen("units"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_UNITS);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "uses", strlen("uses"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_USES);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "value", strlen("value"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_VALUE);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "when", strlen("when"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_WHEN);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "yang-version", strlen("yang-version"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_YANG_VERSION);
+    assert_int_equal(yin_match_keyword(st->yin_ctx, "yin-element", strlen("yin-element"), prefix, prefix_len, LY_STMT_NONE), LY_STMT_YIN_ELEMENT);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_yin_match_argument_name(void **state)
+{
+    (void)state; /* unused */
+
+    assert_int_equal(yin_match_argument_name("", 5), YIN_ARG_UNKNOWN);
+    assert_int_equal(yin_match_argument_name("qwertyasd", 5), YIN_ARG_UNKNOWN);
+    assert_int_equal(yin_match_argument_name("conditionasd", 8), YIN_ARG_UNKNOWN);
+    assert_int_equal(yin_match_argument_name("condition", 9), YIN_ARG_CONDITION);
+    assert_int_equal(yin_match_argument_name("date", 4), YIN_ARG_DATE);
+    assert_int_equal(yin_match_argument_name("module", 6), YIN_ARG_MODULE);
+    assert_int_equal(yin_match_argument_name("name", 4), YIN_ARG_NAME);
+    assert_int_equal(yin_match_argument_name("tag", 3), YIN_ARG_TAG);
+    assert_int_equal(yin_match_argument_name("target-node", 11), YIN_ARG_TARGET_NODE);
+    assert_int_equal(yin_match_argument_name("text", 4), YIN_ARG_TEXT);
+    assert_int_equal(yin_match_argument_name("uri", 3), YIN_ARG_URI);
+    assert_int_equal(yin_match_argument_name("value", 5), YIN_ARG_VALUE);
+}
+
+static void
+test_yin_parse_element_generic(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    struct lysp_ext_instance exts;
+    LY_ERR ret;
+
+    memset(&exts, 0, sizeof(exts));
+
+    const char *data = "<myext:elem attr=\"value\" xmlns:myext=\"urn:example:extensions\">text_value</myext:elem>";
+    lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
+
+    ret = yin_parse_element_generic(st->yin_ctx, LY_STMT_EXTENSION_INSTANCE, &exts.child);
+    assert_int_equal(ret, LY_SUCCESS);
+    assert_int_equal(st->yin_ctx->xmlctx->status, LYXML_ELEM_CLOSE);
+    assert_string_equal(exts.child->stmt, "urn:example:extensions:elem");
+    assert_string_equal(exts.child->arg, "text_value");
+    assert_string_equal(exts.child->child->stmt, "attr");
+    assert_string_equal(exts.child->child->arg, "value");
+    assert_true(exts.child->child->flags & LYS_YIN_ATTR);
+    lysp_ext_instance_free(st->ctx, &exts);
+    st = reset_state(state);
+
+    data = "<myext:elem xmlns:myext=\"urn:example:extensions\"></myext:elem>";
+    lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
+
+    ret = yin_parse_element_generic(st->yin_ctx, LY_STMT_EXTENSION_INSTANCE, &exts.child);
+    assert_int_equal(ret, LY_SUCCESS);
+    assert_int_equal(st->yin_ctx->xmlctx->status, LYXML_ELEM_CLOSE);
+    assert_string_equal(exts.child->stmt, "urn:example:extensions:elem");
+    assert_null(exts.child->child);
+    assert_null(exts.child->arg);
+    lysp_ext_instance_free(st->ctx, &exts);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_yin_parse_extension_instance(void **state)
+{
+    LY_ERR ret;
+    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);
+
+    ret = yin_parse_extension_instance(st->yin_ctx, LYEXT_SUBSTMT_CONTACT, 0, &exts);
+    assert_int_equal(ret, LY_SUCCESS);
+    assert_string_equal(exts->name, "urn:example:extensions:ext");
+    assert_int_equal(exts->insubstmt_index, 0);
+    assert_true(exts->insubstmt == LYEXT_SUBSTMT_CONTACT);
+    assert_true(exts->yin & LYS_YIN);
+    assert_string_equal(exts->child->stmt, "value1");
+    assert_string_equal(exts->child->arg, "test");
+    assert_null(exts->child->child);
+    assert_true(exts->child->flags & LYS_YIN_ATTR);
+    assert_string_equal(exts->child->next->stmt, "value");
+    assert_string_equal(exts->child->next->arg, "test2");
+    assert_null(exts->child->next->child);
+    assert_true(exts->child->next->flags & LYS_YIN_ATTR);
+
+    assert_string_equal(exts->child->next->next->stmt, "urn:example:extensions:subelem");
+    assert_string_equal(exts->child->next->next->arg, "text");
+    assert_null(exts->child->next->next->child);
+    assert_null(exts->child->next->next->next);
+    assert_false(exts->child->next->next->flags & LYS_YIN_ATTR);
+    lysp_ext_instance_free(st->ctx, exts);
+    LY_ARRAY_FREE(exts);
+    exts = NULL;
+    st = reset_state(state);
+
+    data = "<myext:extension-elem xmlns:myext=\"urn:example:extensions\" />";
+    lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
+
+    ret = yin_parse_extension_instance(st->yin_ctx, LYEXT_SUBSTMT_CONTACT, 0, &exts);
+    assert_int_equal(ret, LY_SUCCESS);
+    assert_string_equal(exts->name, "urn:example:extensions:extension-elem");
+    assert_null(exts->argument);
+    assert_null(exts->child);
+    assert_int_equal(exts->insubstmt, LYEXT_SUBSTMT_CONTACT);
+    assert_int_equal(exts->insubstmt_index, 0);
+    assert_true(exts->yin & LYS_YIN);
+    lysp_ext_instance_free(st->ctx, exts);
+    LY_ARRAY_FREE(exts);
+    exts = NULL;
+    st = reset_state(state);
+
+    data = "<myext:ext attr1=\"text1\" attr2=\"text2\" xmlns:myext=\"urn:example:extensions\">"
+                "<myext:ext-sub1/>"
+                "<myext:ext-sub2 sattr1=\"stext2\">"
+                    "<myext:ext-sub21>"
+                        "<myext:ext-sub211 sattr21=\"text21\"/>"
+                    "</myext:ext-sub21>"
+                "</myext:ext-sub2>"
+                "<myext:ext-sub3 attr3=\"text3\"></myext:ext-sub3>"
+           "</myext:ext>";
+    lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
+
+    ret = yin_parse_extension_instance(st->yin_ctx, LYEXT_SUBSTMT_CONTACT, 0, &exts);
+    assert_int_equal(ret, LY_SUCCESS);
+
+    assert_string_equal(exts->name, "urn:example:extensions:ext");
+    assert_null(exts->argument);
+    assert_int_equal(exts->insubstmt, LYEXT_SUBSTMT_CONTACT);
+    assert_int_equal(exts->insubstmt_index, 0);
+    assert_true(exts->yin & LYS_YIN);
+    assert_string_equal(exts->child->stmt, "attr1");
+    assert_string_equal(exts->child->arg, "text1");
+    assert_null(exts->child->child);
+    assert_true(exts->child->flags & LYS_YIN_ATTR);
+
+    assert_string_equal(exts->child->next->stmt, "attr2");
+    assert_string_equal(exts->child->next->arg, "text2");
+    assert_null(exts->child->next->child);
+    assert_true(exts->child->next->flags & LYS_YIN_ATTR);
+
+    assert_string_equal(exts->child->next->next->stmt, "urn:example:extensions:ext-sub1");
+    assert_null(exts->child->next->next->arg);
+    assert_null(exts->child->next->next->child);
+    assert_int_equal(exts->child->next->next->flags, 0);
+
+    assert_string_equal(exts->child->next->next->next->stmt, "urn:example:extensions:ext-sub2");
+    assert_null(exts->child->next->next->next->arg);
+    assert_int_equal(exts->child->next->next->next->flags, 0);
+    assert_string_equal(exts->child->next->next->next->child->stmt, "sattr1");
+    assert_string_equal(exts->child->next->next->next->child->arg, "stext2");
+    assert_null(exts->child->next->next->next->child->child);
+    assert_true(exts->child->next->next->next->child->flags & LYS_YIN_ATTR);
+
+    assert_string_equal(exts->child->next->next->next->child->next->stmt, "urn:example:extensions:ext-sub21");
+    assert_null(exts->child->next->next->next->child->next->arg);
+    assert_null(exts->child->next->next->next->child->next->next);
+    assert_int_equal(exts->child->next->next->next->child->next->flags, 0);
+
+    assert_string_equal(exts->child->next->next->next->child->next->child->stmt, "urn:example:extensions:ext-sub211");
+    assert_null(exts->child->next->next->next->child->next->child->arg);
+    assert_int_equal(exts->child->next->next->next->child->next->child->flags, 0);
+    assert_null(exts->child->next->next->next->child->next->child->next);
+
+    assert_string_equal(exts->child->next->next->next->child->next->child->child->stmt, "sattr21");
+    assert_string_equal(exts->child->next->next->next->child->next->child->child->arg, "text21");
+    assert_null(exts->child->next->next->next->child->next->child->child->next);
+    assert_null(exts->child->next->next->next->child->next->child->child->child);
+    assert_true(exts->child->next->next->next->child->next->child->child->flags & LYS_YIN_ATTR);
+
+    assert_string_equal(exts->child->next->next->next->next->stmt, "urn:example:extensions:ext-sub3");
+    assert_null(exts->child->next->next->next->next->arg);
+    assert_null(exts->child->next->next->next->next->next);
+    assert_int_equal(exts->child->next->next->next->next->flags, 0);
+
+    assert_string_equal(exts->child->next->next->next->next->child->stmt, "attr3");
+    assert_string_equal(exts->child->next->next->next->next->child->arg, "text3");
+    assert_null(exts->child->next->next->next->next->child->next);
+    assert_null(exts->child->next->next->next->next->child->child);
+    assert_true(exts->child->next->next->next->next->child->flags & LYS_YIN_ATTR);
+
+    lysp_ext_instance_free(st->ctx, exts);
+    LY_ARRAY_FREE(exts);
+    exts = NULL;
+    st = reset_state(state);
+
+    data = "<myext:extension-elem xmlns:myext=\"urn:example:extensions\" xmlns:yin=\"urn:ietf:params:xml:ns:yang:yin:1\">"
+                "<yin:action name=\"act-name\" pre:prefixed=\"ignored\"/>"
+                "<yin:augment target-node=\"target\"/>"
+                "<yin:status value=\"value\"/>"
+                "<yin:include module=\"mod\"/>"
+                "<yin:input />"
+                "<yin:must condition=\"cond\"/>"
+                "<yin:namespace uri=\"uri\"/>"
+                "<yin:revision date=\"data\"/>"
+                "<yin:unique tag=\"tag\"/>"
+                "<yin:description><yin:text>contact-val</yin:text></yin:description>"
+                "<yin:error-message><yin:value>err-msg</yin:value></yin:error-message>"
+           "</myext:extension-elem>";
+    lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
+
+    ret = yin_parse_extension_instance(st->yin_ctx, LYEXT_SUBSTMT_CONTACT, 0, &exts);
+    assert_int_equal(ret, LY_SUCCESS);
+    assert_string_equal(exts->child->arg, "act-name");
+    assert_string_equal(exts->child->next->arg, "target");
+    assert_string_equal(exts->child->next->next->arg, "value");
+    assert_string_equal(exts->child->next->next->next->arg, "mod");
+    assert_null(exts->child->next->next->next->next->arg);
+    assert_string_equal(exts->child->next->next->next->next->next->arg, "cond");
+    assert_string_equal(exts->child->next->next->next->next->next->next->arg, "uri");
+    assert_string_equal(exts->child->next->next->next->next->next->next->next->arg, "data");
+    assert_string_equal(exts->child->next->next->next->next->next->next->next->next->arg, "tag");
+    assert_string_equal(exts->child->next->next->next->next->next->next->next->next->next->arg, "contact-val");
+    lysp_ext_instance_free(st->ctx, exts);
+    LY_ARRAY_FREE(exts);
+    exts = NULL;
+    st = reset_state(state);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_yin_parse_content(void **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\">"
+                                "totally amazing extension"
+                            "</myext:custom>"
+                            "<extension name=\"ext\">"
+                                "<argument name=\"argname\"></argument>"
+                                "<description><text>desc</text></description>"
+                                "<reference><text>ref</text></reference>"
+                                "<status value=\"deprecated\"></status>"
+                            "</extension>"
+                            "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
+                            "<if-feature name=\"foo\"></if-feature>"
+                            "<when condition=\"condition...\">"
+                                "<reference><text>when_ref</text></reference>"
+                                "<description><text>when_desc</text></description>"
+                            "</when>"
+                            "<config value=\"true\"/>"
+                            "<error-message>"
+                                "<value>error-msg</value>"
+                            "</error-message>"
+                            "<error-app-tag value=\"err-app-tag\"/>"
+                            "<units name=\"radians\"></units>"
+                            "<default value=\"default-value\"/>"
+                            "<position value=\"25\"></position>"
+                            "<value value=\"-5\"/>"
+                            "<require-instance value=\"true\"></require-instance>"
+                            "<range value=\"5..10\" />"
+                            "<length value=\"baf\"/>"
+                            "<pattern value='pattern'>"
+                                "<modifier value='invert-match'/>"
+                            "</pattern>"
+                            "<enum name=\"yay\">"
+                            "</enum>"
+                        "</prefix>";
+    struct lysp_ext_instance *exts = NULL;
+    const char **if_features = NULL;
+    const char *value, *err_msg, *app_tag, *units, *def;
+    struct lysp_ext *ext_def = NULL;
+    struct lysp_when *when_p = NULL;
+    struct lysp_type_enum pos_enum = {}, val_enum = {};
+    struct lysp_type req_type = {}, range_type = {}, len_type = {}, patter_type = {}, enum_type = {};
+    uint8_t config = 0;
+
+    lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
+    lyxml_ctx_next(st->yin_ctx->xmlctx);
+    lyxml_ctx_next(st->yin_ctx->xmlctx);
+    lyxml_ctx_next(st->yin_ctx->xmlctx);
+
+    struct yin_subelement subelems[17] = {
+                                            {LY_STMT_CONFIG, &config, 0},
+                                            {LY_STMT_DEFAULT, &def, YIN_SUBELEM_UNIQUE},
+                                            {LY_STMT_ENUM, &enum_type, 0},
+                                            {LY_STMT_ERROR_APP_TAG, &app_tag, YIN_SUBELEM_UNIQUE},
+                                            {LY_STMT_ERROR_MESSAGE, &err_msg, 0},
+                                            {LY_STMT_EXTENSION, &ext_def, 0},
+                                            {LY_STMT_IF_FEATURE, &if_features, 0},
+                                            {LY_STMT_LENGTH, &len_type, 0},
+                                            {LY_STMT_PATTERN, &patter_type, 0},
+                                            {LY_STMT_POSITION, &pos_enum, 0},
+                                            {LY_STMT_RANGE, &range_type, 0},
+                                            {LY_STMT_REQUIRE_INSTANCE, &req_type, 0},
+                                            {LY_STMT_UNITS, &units, YIN_SUBELEM_UNIQUE},
+                                            {LY_STMT_VALUE, &val_enum, 0},
+                                            {LY_STMT_WHEN, &when_p, 0},
+                                            {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
+                                            {LY_STMT_ARG_TEXT, &value, 0}
+                                         };
+    ret = yin_parse_content(st->yin_ctx, subelems, 17, LY_STMT_PREFIX, NULL, &exts);
+    assert_int_equal(ret, LY_SUCCESS);
+    /* check parsed values */
+    assert_string_equal(def, "default-value");
+    assert_string_equal(exts->name, "urn:example:extensions:custom");
+    assert_string_equal(exts->argument, "totally amazing extension");
+    assert_string_equal(value, "wsefsdf");
+    assert_string_equal(units, "radians");
+    assert_string_equal(when_p->cond, "condition...");
+    assert_string_equal(when_p->dsc, "when_desc");
+    assert_string_equal(when_p->ref, "when_ref");
+    assert_int_equal(config, LYS_CONFIG_W);
+    assert_int_equal(pos_enum.value, 25);
+    assert_true(pos_enum.flags & LYS_SET_VALUE);
+    assert_int_equal(val_enum.value, -5);
+    assert_true(val_enum.flags & LYS_SET_VALUE);
+    assert_int_equal(req_type.require_instance, 1);
+    assert_true(req_type.flags &= LYS_SET_REQINST);
+    assert_string_equal(range_type.range->arg, "5..10");
+    assert_true(range_type.flags & LYS_SET_RANGE);
+    assert_string_equal(err_msg, "error-msg");
+    assert_string_equal(app_tag, "err-app-tag");
+    assert_string_equal(enum_type.enums->name, "yay");
+    assert_string_equal(len_type.length->arg, "baf");
+    assert_true(len_type.flags & LYS_SET_LENGTH);
+    assert_string_equal(patter_type.patterns->arg, "\x015pattern");
+    assert_true(patter_type.flags & LYS_SET_PATTERN);
+    /* cleanup */
+    lysp_ext_instance_free(st->ctx, exts);
+    lysp_when_free(st->ctx, when_p);
+    lysp_ext_free(st->ctx, ext_def);
+    FREE_STRING(st->ctx, *if_features);
+    FREE_STRING(st->ctx, err_msg);
+    FREE_STRING(st->ctx, app_tag);
+    FREE_STRING(st->ctx, units);
+    FREE_STRING(st->ctx, patter_type.patterns->arg);
+    FREE_STRING(st->ctx, def);
+    FREE_STRING(st->ctx, range_type.range->arg);
+    FREE_STRING(st->ctx, len_type.length->arg);
+    FREE_STRING(st->ctx, enum_type.enums->name);
+    FREE_STRING(st->ctx, value);
+    LY_ARRAY_FREE(if_features);
+    LY_ARRAY_FREE(exts);
+    LY_ARRAY_FREE(ext_def);
+    LY_ARRAY_FREE(patter_type.patterns);
+    LY_ARRAY_FREE(enum_type.enums);
+    free(when_p);
+    free(range_type.range);
+    free(len_type.length);
+    st = reset_state(state);
+
+    /* test unique subelem */
+    const char *prefix_value;
+    struct yin_subelement subelems2[2] = {{LY_STMT_PREFIX, &prefix_value, YIN_SUBELEM_UNIQUE},
+                                         {LY_STMT_ARG_TEXT, &value, YIN_SUBELEM_UNIQUE}};
+    data = ELEMENT_WRAPPER_START
+                "<prefix value=\"inv_mod\" />"
+                "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
+                "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
+           ELEMENT_WRAPPER_END;
+    lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
+    lyxml_ctx_next(st->yin_ctx->xmlctx);
+
+    ret = yin_parse_content(st->yin_ctx, subelems2, 2, LY_STMT_STATUS, NULL, &exts);
+    assert_int_equal(ret, LY_EVALID);
+    logbuf_assert("Redefinition of \"text\" sub-element in \"status\" element. Line number 1.");
+    lydict_remove(st->ctx, prefix_value);
+    lydict_remove(st->ctx, value);
+    st = reset_state(state);
+
+    /* test first subelem */
+    data = ELEMENT_WRAPPER_START
+                "<prefix value=\"inv_mod\" />"
+                "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
+                "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
+           ELEMENT_WRAPPER_END;
+    struct yin_subelement subelems3[2] = {{LY_STMT_PREFIX, &prefix_value, YIN_SUBELEM_UNIQUE},
+                                         {LY_STMT_ARG_TEXT, &value, YIN_SUBELEM_FIRST}};
+    lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
+    lyxml_ctx_next(st->yin_ctx->xmlctx);
+
+    ret = yin_parse_content(st->yin_ctx, subelems3, 2, LY_STMT_STATUS, NULL, &exts);
+    assert_int_equal(ret, LY_EVALID);
+    logbuf_assert("Sub-element \"text\" of \"status\" element must be defined as it's first sub-element. Line number 1.");
+    lydict_remove(st->ctx, prefix_value);
+    st = reset_state(state);
+
+    /* test mandatory subelem */
+    data = ELEMENT_WRAPPER_START ELEMENT_WRAPPER_END;
+    struct yin_subelement subelems4[1] = {{LY_STMT_PREFIX, &prefix_value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE}};
+    lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
+    lyxml_ctx_next(st->yin_ctx->xmlctx);
+
+    ret = yin_parse_content(st->yin_ctx, subelems4, 1, LY_STMT_STATUS, NULL, &exts);
+    assert_int_equal(ret, LY_EVALID);
+    logbuf_assert("Missing mandatory sub-element \"prefix\" of \"status\" element. Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_validate_value(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data = ELEMENT_WRAPPER_START ELEMENT_WRAPPER_END;
+
+    /* create some XML context */
+    lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
+    st->yin_ctx->xmlctx->status = LYXML_ELEM_CONTENT;
+    st->yin_ctx->xmlctx->dynamic = 0;
+
+    st->yin_ctx->xmlctx->value = "#invalid";
+    st->yin_ctx->xmlctx->value_len = 8;
+    assert_int_equal(yin_validate_value(st->yin_ctx, Y_IDENTIF_ARG), LY_EVALID);
+    logbuf_assert("Invalid identifier character '#'. Line number 1.");
+
+    st->yin_ctx->xmlctx->value = "";
+    st->yin_ctx->xmlctx->value_len = 0;
+    assert_int_equal(yin_validate_value(st->yin_ctx, Y_STR_ARG), LY_SUCCESS);
+
+    st->yin_ctx->xmlctx->value = "pre:b";
+    st->yin_ctx->xmlctx->value_len = 5;
+    assert_int_equal(yin_validate_value(st->yin_ctx, Y_IDENTIF_ARG), LY_EVALID);
+    assert_int_equal(yin_validate_value(st->yin_ctx, Y_PREF_IDENTIF_ARG), LY_SUCCESS);
+
+    st->yin_ctx->xmlctx->value = "pre:pre:b";
+    st->yin_ctx->xmlctx->value_len = 9;
+    assert_int_equal(yin_validate_value(st->yin_ctx, Y_PREF_IDENTIF_ARG), LY_EVALID);
+
+    st->finished_correctly = true;
+}
+
+/* helper function to simplify unit test of each element using parse_content function */
+LY_ERR
+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;
+    LY_ERR ret = LY_SUCCESS;
+    struct yin_subelement subelems[71] = {
+                                            {LY_STMT_ACTION, dest, 0},
+                                            {LY_STMT_ANYDATA, dest, 0},
+                                            {LY_STMT_ANYXML, dest, 0},
+                                            {LY_STMT_ARGUMENT,dest, 0},
+                                            {LY_STMT_AUGMENT, dest, 0},
+                                            {LY_STMT_BASE, dest, 0},
+                                            {LY_STMT_BELONGS_TO, dest, 0},
+                                            {LY_STMT_BIT, dest, 0},
+                                            {LY_STMT_CASE, dest, 0},
+                                            {LY_STMT_CHOICE, dest, 0},
+                                            {LY_STMT_CONFIG, dest, 0},
+                                            {LY_STMT_CONTACT, dest, 0},
+                                            {LY_STMT_CONTAINER, dest, 0},
+                                            {LY_STMT_DEFAULT, dest, YIN_SUBELEM_UNIQUE},
+                                            {LY_STMT_DESCRIPTION, dest, 0},
+                                            {LY_STMT_DEVIATE, dest, 0},
+                                            {LY_STMT_DEVIATION, dest, 0},
+                                            {LY_STMT_ENUM, dest, 0},
+                                            {LY_STMT_ERROR_APP_TAG, dest, YIN_SUBELEM_UNIQUE},
+                                            {LY_STMT_ERROR_MESSAGE, dest, 0},
+                                            {LY_STMT_EXTENSION, dest, 0},
+                                            {LY_STMT_FEATURE, dest, 0},
+                                            {LY_STMT_FRACTION_DIGITS, dest, 0},
+                                            {LY_STMT_GROUPING, dest, 0},
+                                            {LY_STMT_IDENTITY, dest, 0},
+                                            {LY_STMT_IF_FEATURE, dest, 0},
+                                            {LY_STMT_IMPORT, dest, 0},
+                                            {LY_STMT_INCLUDE, dest, 0},
+                                            {LY_STMT_INPUT, dest, 0},
+                                            {LY_STMT_KEY, dest, YIN_SUBELEM_UNIQUE},
+                                            {LY_STMT_LEAF, dest, 0},
+                                            {LY_STMT_LEAF_LIST, dest, 0},
+                                            {LY_STMT_LENGTH, dest, 0},
+                                            {LY_STMT_LIST, dest, 0},
+                                            {LY_STMT_MANDATORY, dest, 0},
+                                            {LY_STMT_MAX_ELEMENTS, dest, 0},
+                                            {LY_STMT_MIN_ELEMENTS, dest, 0},
+                                            {LY_STMT_MODIFIER, dest, 0},
+                                            {LY_STMT_MODULE, dest, 0},
+                                            {LY_STMT_MUST, dest, 0},
+                                            {LY_STMT_NAMESPACE, dest, YIN_SUBELEM_UNIQUE},
+                                            {LY_STMT_NOTIFICATION, dest, 0},
+                                            {LY_STMT_ORDERED_BY, dest, 0},
+                                            {LY_STMT_ORGANIZATION, dest, 0},
+                                            {LY_STMT_OUTPUT, dest, 0},
+                                            {LY_STMT_PATH, dest, 0},
+                                            {LY_STMT_PATTERN, dest, 0},
+                                            {LY_STMT_POSITION, dest, 0},
+                                            {LY_STMT_PREFIX, dest, YIN_SUBELEM_UNIQUE},
+                                            {LY_STMT_PRESENCE, dest, YIN_SUBELEM_UNIQUE},
+                                            {LY_STMT_RANGE, dest, 0},
+                                            {LY_STMT_REFERENCE, dest, 0},
+                                            {LY_STMT_REFINE, dest, 0},
+                                            {LY_STMT_REQUIRE_INSTANCE, dest, 0},
+                                            {LY_STMT_REVISION, dest, 0},
+                                            {LY_STMT_REVISION_DATE, dest, 0},
+                                            {LY_STMT_RPC, dest, 0},
+                                            {LY_STMT_STATUS, dest, 0},
+                                            {LY_STMT_SUBMODULE, dest, 0},
+                                            {LY_STMT_TYPE, dest, 0},
+                                            {LY_STMT_TYPEDEF, dest, 0},
+                                            {LY_STMT_UNIQUE, dest, 0},
+                                            {LY_STMT_UNITS, dest, YIN_SUBELEM_UNIQUE},
+                                            {LY_STMT_USES, dest, 0},
+                                            {LY_STMT_VALUE, dest, 0},
+                                            {LY_STMT_WHEN, dest, 0},
+                                            {LY_STMT_YANG_VERSION, dest, 0},
+                                            {LY_STMT_YIN_ELEMENT, dest, 0},
+                                            {LY_STMT_EXTENSION_INSTANCE, dest, 0},
+                                            {LY_STMT_ARG_TEXT, dest, 0},
+                                            {LY_STMT_ARG_VALUE, dest, 0}
+                                        };
+    lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx);
+    prefix = st->yin_ctx->xmlctx->prefix;
+    prefix_len = st->yin_ctx->xmlctx->prefix_len;
+    name = st->yin_ctx->xmlctx->name;
+    name_len = st->yin_ctx->xmlctx->name_len;
+    lyxml_ctx_next(st->yin_ctx->xmlctx);
+
+    ret = yin_parse_content(st->yin_ctx, subelems, 71, yin_match_keyword(st->yin_ctx, name, name_len, prefix, prefix_len, LY_STMT_NONE), text, exts);
+
+    /* free parser */
+    lyxml_ctx_free(st->yin_ctx->xmlctx);
+    st->yin_ctx->xmlctx = NULL;
+    return ret;
+}
+
+#define EXT_SUBELEM "<myext:c-define name=\"MY_MTU\" xmlns:myext=\"urn:example:extensions\"/>"
+
+static void
+test_enum_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    struct lysp_type type = {};
+    const char *data;
+    data = ELEMENT_WRAPPER_START
+           "<enum name=\"enum-name\">"
+                "<if-feature name=\"feature\" />"
+                "<value value=\"55\" />"
+                "<status value=\"deprecated\" />"
+                "<description><text>desc...</text></description>"
+                "<reference><text>ref...</text></reference>"
+                EXT_SUBELEM
+           "</enum>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(type.enums->name, "enum-name");
+    assert_string_equal(*type.enums->iffeatures, "feature");
+    assert_int_equal(type.enums->value, 55);
+    assert_true((type.enums->flags & LYS_STATUS_DEPRC) && (type.enums->flags & LYS_SET_VALUE));
+    assert_string_equal(type.enums->dsc, "desc...");
+    assert_string_equal(type.enums->ref, "ref...");
+    assert_string_equal(type.enums->exts->name, "urn:example:extensions:c-define");
+    assert_int_equal(type.enums->exts->insubstmt_index, 0);
+    assert_int_equal(type.enums->exts->insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof type);
+
+    data = ELEMENT_WRAPPER_START
+           "<enum name=\"enum-name\"></enum>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(type.enums->name, "enum-name");
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof type);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_bit_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    struct lysp_type type = {};
+    const char *data;
+    data = ELEMENT_WRAPPER_START
+           "<bit name=\"bit-name\">"
+                "<if-feature name=\"feature\" />"
+                "<position value=\"55\" />"
+                "<status value=\"deprecated\" />"
+                "<description><text>desc...</text></description>"
+                "<reference><text>ref...</text></reference>"
+                EXT_SUBELEM
+           "</bit>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(type.bits->name, "bit-name");
+    assert_string_equal(*type.bits->iffeatures, "feature");
+    assert_int_equal(type.bits->value, 55);
+    assert_true((type.bits->flags & LYS_STATUS_DEPRC) && (type.bits->flags & LYS_SET_VALUE));
+    assert_string_equal(type.bits->dsc, "desc...");
+    assert_string_equal(type.bits->ref, "ref...");
+    assert_string_equal(type.bits->exts->name, "urn:example:extensions:c-define");
+    assert_int_equal(type.bits->exts->insubstmt_index, 0);
+    assert_int_equal(type.bits->exts->insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof type);
+
+    data = ELEMENT_WRAPPER_START
+           "<bit name=\"bit-name\"> </bit>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(type.bits->name, "bit-name");
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof type);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_meta_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    char *value = NULL;
+    const char *data;
+    struct lysp_ext_instance *exts = NULL;
+
+    /* organization element */
+    data = ELEMENT_WRAPPER_START
+                "<organization><text>organization...</text>" EXT_SUBELEM EXT_SUBELEM "</organization>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &value, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_ORGANIZATION);
+    assert_string_equal(exts[1].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[1].insubstmt_index, 0);
+    assert_int_equal(exts[1].insubstmt, LYEXT_SUBSTMT_ORGANIZATION);
+    assert_string_equal(value, "organization...");
+    FREE_STRING(st->ctx, value);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    value = NULL;
+    exts = NULL;
+
+    /* contact element */
+    data = ELEMENT_WRAPPER_START
+                "<contact><text>contact...</text>" EXT_SUBELEM "</contact>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &value, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_CONTACT);
+    assert_string_equal(value, "contact...");
+    FREE_STRING(st->ctx, value);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    value = NULL;
+
+    /* description element */
+    data = ELEMENT_WRAPPER_START
+                "<description><text>description...</text>" EXT_SUBELEM "</description>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &value, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(value, "description...");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_DESCRIPTION);
+    FREE_STRING(st->ctx, value);
+    value = NULL;
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+
+    /* reference element */
+    data = ELEMENT_WRAPPER_START
+                "<reference><text>reference...</text>" EXT_SUBELEM "</reference>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &value, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(value, "reference...");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_REFERENCE);
+    FREE_STRING(st->ctx, value);
+    value = NULL;
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+
+    /* reference element */
+    data = ELEMENT_WRAPPER_START
+                "<reference invalid=\"text\"><text>reference...</text>""</reference>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &value, NULL, &exts), LY_EVALID);
+    logbuf_assert("Unexpected attribute \"invalid\" of \"reference\" element. Line number 1.");
+    FREE_STRING(st->ctx, value);
+    value = NULL;
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+
+    /* missing text subelement */
+    data = ELEMENT_WRAPPER_START
+                "<reference>reference...</reference>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &value, NULL, &exts), LY_EVALID);
+    logbuf_assert("Missing mandatory sub-element \"text\" of \"reference\" element. Line number 1.");
+
+    /* reference element */
+    data = ELEMENT_WRAPPER_START
+                "<reference>" EXT_SUBELEM "<text>reference...</text></reference>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &value, NULL, &exts), LY_EVALID);
+    logbuf_assert("Sub-element \"text\" of \"reference\" element must be defined as it's first sub-element. Line number 1.");
+    FREE_STRING(st->ctx, value);
+    value = NULL;
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_import_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_import *imports = NULL;
+    struct import_meta imp_meta = {"prefix", &imports};
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<import module=\"a\">"
+                    EXT_SUBELEM
+                    "<prefix value=\"a_mod\"/>"
+                    "<revision-date date=\"2015-01-01\"></revision-date>"
+                    "<description><text>import description</text></description>"
+                    "<reference><text>import reference</text></reference>"
+                "</import>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &imp_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(imports->name, "a");
+    assert_string_equal(imports->prefix, "a_mod");
+    assert_string_equal(imports->rev, "2015-01-01");
+    assert_string_equal(imports->dsc, "import description");
+    assert_string_equal(imports->ref, "import reference");
+    assert_string_equal(imports->exts->name, "urn:example:extensions:c-define");
+    assert_int_equal(imports->exts->insubstmt, LYEXT_SUBSTMT_SELF);
+    assert_int_equal(imports->exts->insubstmt_index, 0);
+    FREE_ARRAY(st->ctx, imports, lysp_import_free);
+    imports = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START
+                "<import module=\"a\">"
+                    "<prefix value=\"a_mod\"/>"
+                "</import>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &imp_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(imports->prefix, "a_mod");
+    FREE_ARRAY(st->ctx, imports, lysp_import_free);
+    imports = NULL;
+
+    /* invalid (missing prefix) */
+    data = ELEMENT_WRAPPER_START "<import module=\"a\"></import>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &imp_meta, NULL, NULL), LY_EVALID);
+    logbuf_assert("Missing mandatory sub-element \"prefix\" of \"import\" element. Line number 1.");
+    FREE_ARRAY(st->ctx, imports, lysp_import_free);
+    imports = NULL;
+
+    /* invalid reused prefix */
+    data = ELEMENT_WRAPPER_START
+                "<import module=\"a\">"
+                    "<prefix value=\"prefix\"/>"
+                "</import>"
+                "<import module=\"a\">"
+                    "<prefix value=\"prefix\"/>"
+                "</import>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &imp_meta, NULL, NULL), LY_EVALID);
+    logbuf_assert("Prefix \"prefix\" already used as module prefix. Line number 1.");
+    FREE_ARRAY(st->ctx, imports, lysp_import_free);
+    imports = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_status_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    uint16_t flags = 0;
+    struct lysp_ext_instance *exts = NULL;
+
+    /* test valid values */
+    data = ELEMENT_WRAPPER_START "<status value=\"current\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, NULL), LY_SUCCESS);
+    assert_true(flags & LYS_STATUS_CURR);
+
+    data = ELEMENT_WRAPPER_START "<status value=\"deprecated\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, NULL), LY_SUCCESS);
+    assert_true(flags & LYS_STATUS_DEPRC);
+
+    data = ELEMENT_WRAPPER_START "<status value=\"obsolete\">"EXT_SUBELEM"</status>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, &exts), LY_SUCCESS);
+    assert_true(flags & LYS_STATUS_OBSLT);
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_STATUS);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+
+    /* test invalid value */
+    data = ELEMENT_WRAPPER_START "<status value=\"invalid\"></status>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"invalid\" of \"value\" attribute in \"status\" element. Valid values are \"current\", \"deprecated\" and \"obsolete\". Line number 1.");
+    st->finished_correctly = true;
+}
+
+static void
+test_ext_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_ext *ext = NULL;
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+           "<extension name=\"ext_name\">"
+                "<argument name=\"arg\"></argument>"
+                "<status value=\"current\"/>"
+                "<description><text>ext_desc</text></description>"
+                "<reference><text>ext_ref</text></reference>"
+                EXT_SUBELEM
+           "</extension>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &ext, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(ext->name, "ext_name");
+    assert_string_equal(ext->argument, "arg");
+    assert_true(ext->flags & LYS_STATUS_CURR);
+    assert_string_equal(ext->dsc, "ext_desc");
+    assert_string_equal(ext->ref, "ext_ref");
+    assert_string_equal(ext->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(ext->exts[0].insubstmt_index, 0);
+    assert_int_equal(ext->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_ext_free(st->ctx, ext);
+    LY_ARRAY_FREE(ext);
+    ext = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<extension name=\"ext_name\"></extension>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &ext, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(ext->name, "ext_name");
+    lysp_ext_free(st->ctx, ext);
+    LY_ARRAY_FREE(ext);
+    ext = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_yin_element_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    uint16_t flags = 0;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<yin-element value=\"true\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, NULL), LY_SUCCESS);
+    assert_true(flags & LYS_YINELEM_TRUE);
+
+    data = ELEMENT_WRAPPER_START "<yin-element value=\"false\">" EXT_SUBELEM "</yin-element>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, &exts), LY_SUCCESS);
+    assert_true(flags & LYS_YINELEM_TRUE);
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_YINELEM);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+
+    data = ELEMENT_WRAPPER_START "<yin-element value=\"invalid\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, NULL), LY_EVALID);
+    assert_true(flags & LYS_YINELEM_TRUE);
+    logbuf_assert("Invalid value \"invalid\" of \"value\" attribute in \"yin-element\" element. Valid values are \"true\" and \"false\". Line number 1.");
+    st->finished_correctly = true;
+}
+
+static void
+test_yangversion_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    uint8_t version = 0;
+    struct lysp_ext_instance *exts = NULL;
+
+    /* valid values */
+    data = ELEMENT_WRAPPER_START "<yang-version value=\"1.0\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &version, NULL, NULL), LY_SUCCESS);
+    assert_true(version & LYS_VERSION_1_0);
+    assert_int_equal(st->yin_ctx->mod_version, LYS_VERSION_1_0);
+
+    data = ELEMENT_WRAPPER_START "<yang-version value=\"1.1\">" EXT_SUBELEM "</yang-version>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &version, NULL, &exts), LY_SUCCESS);
+    assert_true(version & LYS_VERSION_1_1);
+    assert_int_equal(st->yin_ctx->mod_version, LYS_VERSION_1_1);
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_VERSION);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+
+    /* invalid value */
+    data = ELEMENT_WRAPPER_START "<yang-version value=\"version\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &version, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"version\" of \"value\" attribute in \"yang-version\" element. Valid values are \"1.0\" and \"1.1\". Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_mandatory_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    uint16_t man = 0;
+    struct lysp_ext_instance *exts = NULL;
+
+    /* valid values */
+    data = ELEMENT_WRAPPER_START "<mandatory value=\"true\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &man, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(man, LYS_MAND_TRUE);
+    man = 0;
+
+    data = ELEMENT_WRAPPER_START "<mandatory value=\"false\">" EXT_SUBELEM "</mandatory>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &man, NULL, &exts), LY_SUCCESS);
+    assert_int_equal(man, LYS_MAND_FALSE);
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_MANDATORY);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+
+    data = ELEMENT_WRAPPER_START "<mandatory value=\"invalid\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &man, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"invalid\" of \"value\" attribute in \"mandatory\" element. Valid values are \"true\" and \"false\". Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_argument_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    uint16_t flags = 0;
+    const char *arg;
+    struct yin_argument_meta arg_meta = {&flags, &arg};
+    struct lysp_ext_instance *exts = NULL;
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+           "<argument name=\"arg-name\">"
+                "<yin-element value=\"true\" />"
+                EXT_SUBELEM
+           "</argument>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &arg_meta, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(arg, "arg-name");
+    assert_true(flags & LYS_YINELEM_TRUE);
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_ARGUMENT);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    flags = 0;
+    FREE_STRING(st->ctx, arg);
+    arg = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START
+           "<argument name=\"arg\">"
+           "</argument>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &arg_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(arg, "arg");
+    assert_true(flags == 0);
+    FREE_STRING(st->ctx, arg);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_base_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    const char **bases = NULL;
+    struct lysp_ext_instance *exts = NULL;
+    struct lysp_type type = {};
+
+    /* as identity subelement */
+    data = "<identity xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
+                "<base name=\"base-name\">"
+                    EXT_SUBELEM
+                "</base>"
+           "</identity>";
+    assert_int_equal(test_element_helper(st, data, &bases, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(*bases, "base-name");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_BASE);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    FREE_STRING(st->ctx, *bases);
+    LY_ARRAY_FREE(bases);
+
+    /* as type subelement */
+    data = "<type xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
+                "<base name=\"base-name\">"
+                    EXT_SUBELEM
+                "</base>"
+           "</type>";
+    assert_int_equal(test_element_helper(st, data, &type, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(*type.bases, "base-name");
+    assert_true(type.flags & LYS_SET_BASE);
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_BASE);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    FREE_STRING(st->ctx, *type.bases);
+    LY_ARRAY_FREE(type.bases);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_belongsto_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_submodule submod;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<belongs-to module=\"module-name\"><prefix value=\"pref\"/>"EXT_SUBELEM"</belongs-to>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &submod, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(submod.belongsto, "module-name");
+    assert_string_equal(submod.prefix, "pref");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_BELONGSTO);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    FREE_STRING(st->ctx, submod.belongsto);
+    FREE_STRING(st->ctx, submod.prefix);
+
+    data = ELEMENT_WRAPPER_START "<belongs-to module=\"module-name\"></belongs-to>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &submod, NULL, NULL), LY_EVALID);
+    logbuf_assert("Missing mandatory sub-element \"prefix\" of \"belongs-to\" element. Line number 1.");
+    FREE_STRING(st->ctx, submod.belongsto);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_config_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    uint16_t flags = 0;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<config value=\"true\">" EXT_SUBELEM "</config>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, &exts), LY_SUCCESS);
+    assert_true(flags & LYS_CONFIG_W);
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_CONFIG);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    flags = 0;
+
+    data = ELEMENT_WRAPPER_START "<config value=\"false\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, NULL), LY_SUCCESS);
+    assert_true(flags & LYS_CONFIG_R);
+    flags = 0;
+
+    data = ELEMENT_WRAPPER_START "<config value=\"invalid\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"invalid\" of \"value\" attribute in \"config\" element. Valid values are \"true\" and \"false\". Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_default_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    const char *val = NULL;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<default value=\"defaul-value\">"EXT_SUBELEM"</default>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(val, "defaul-value");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_DEFAULT);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    FREE_STRING(st->ctx, val);
+    val = NULL;
+
+    data = ELEMENT_WRAPPER_START "<default/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, NULL), LY_EVALID);
+    logbuf_assert("Missing mandatory attribute value of default element. Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_err_app_tag_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    const char *val = NULL;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<error-app-tag value=\"val\">"EXT_SUBELEM"</error-app-tag>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(val, "val");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_ERRTAG);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    FREE_STRING(st->ctx, val);
+    val = NULL;
+
+    data = ELEMENT_WRAPPER_START "<error-app-tag/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, NULL), LY_EVALID);
+    logbuf_assert("Missing mandatory attribute value of error-app-tag element. Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_err_msg_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    const char *val = NULL;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<error-message><value>val</value>"EXT_SUBELEM"</error-message>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(val, "val");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_ERRMSG);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    FREE_STRING(st->ctx, val);
+
+    data = ELEMENT_WRAPPER_START "<error-message></error-message>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, NULL), LY_EVALID);
+    logbuf_assert("Missing mandatory sub-element \"value\" of \"error-message\" element. Line number 1.");
+
+    data = ELEMENT_WRAPPER_START "<error-message invalid=\"text\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, NULL), LY_EVALID);
+    logbuf_assert("Unexpected attribute \"invalid\" of \"error-message\" element. Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_fracdigits_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_type type = {};
+
+    /* valid value */
+    data = ELEMENT_WRAPPER_START "<fraction-digits value=\"10\">"EXT_SUBELEM"</fraction-digits>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(type.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(type.exts[0].insubstmt_index, 0);
+    assert_int_equal(type.exts[0].insubstmt, LYEXT_SUBSTMT_FRACDIGITS);
+    assert_int_equal(type.fraction_digits, 10);
+    assert_true(type.flags & LYS_SET_FRDIGITS);
+    FREE_ARRAY(st->ctx, type.exts, lysp_ext_instance_free);
+
+    /* invalid values */
+    data = ELEMENT_WRAPPER_START "<fraction-digits value=\"-1\"></fraction-digits>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"-1\" of \"value\" attribute in \"fraction-digits\" element. Line number 1.");
+
+    data = ELEMENT_WRAPPER_START "<fraction-digits value=\"02\"></fraction-digits>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"02\" of \"value\" attribute in \"fraction-digits\" element. Line number 1.");
+
+    data = ELEMENT_WRAPPER_START "<fraction-digits value=\"1p\"></fraction-digits>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"1p\" of \"value\" attribute in \"fraction-digits\" element. Line number 1.");
+
+    data = ELEMENT_WRAPPER_START "<fraction-digits value=\"19\"></fraction-digits>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"19\" of \"value\" attribute in \"fraction-digits\" element. Line number 1.");
+
+    data = ELEMENT_WRAPPER_START "<fraction-digits value=\"999999999999999999\"></fraction-digits>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"999999999999999999\" of \"value\" attribute in \"fraction-digits\" element. Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_iffeature_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    const char **iffeatures = NULL;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<if-feature name=\"local-storage\">"EXT_SUBELEM"</if-feature>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &iffeatures, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(*iffeatures, "local-storage");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_IFFEATURE);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    FREE_STRING(st->ctx, *iffeatures);
+    LY_ARRAY_FREE(iffeatures);
+    iffeatures = NULL;
+
+    data = ELEMENT_WRAPPER_START "<if-feature/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &iffeatures, NULL, NULL), LY_EVALID);
+    logbuf_assert("Missing mandatory attribute name of if-feature element. Line number 1.");
+    LY_ARRAY_FREE(iffeatures);
+    iffeatures = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_length_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_type type = {};
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<length value=\"length-str\">"
+                    "<error-message><value>err-msg</value></error-message>"
+                    "<error-app-tag value=\"err-app-tag\"/>"
+                    "<description><text>desc</text></description>"
+                    "<reference><text>ref</text></reference>"
+                    EXT_SUBELEM
+                "</length>"
+            ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(type.length->arg, "length-str");
+    assert_string_equal(type.length->emsg, "err-msg");
+    assert_string_equal(type.length->eapptag, "err-app-tag");
+    assert_string_equal(type.length->dsc, "desc");
+    assert_string_equal(type.length->ref, "ref");
+    assert_true(type.flags & LYS_SET_LENGTH);
+    assert_string_equal(type.length->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(type.length->exts[0].insubstmt_index, 0);
+    assert_int_equal(type.length->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof(type));
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START
+                "<length value=\"length-str\">"
+                "</length>"
+            ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(type.length->arg, "length-str");
+    lysp_type_free(st->ctx, &type);
+    assert_true(type.flags & LYS_SET_LENGTH);
+    memset(&type, 0, sizeof(type));
+
+    data = ELEMENT_WRAPPER_START "<length></length>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_EVALID);
+    logbuf_assert("Missing mandatory attribute value of length element. Line number 1.");
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof(type));
+
+    st->finished_correctly = true;
+}
+
+static void
+test_modifier_elem(void **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;
+
+    data = ELEMENT_WRAPPER_START "<modifier value=\"invert-match\">" EXT_SUBELEM "</modifier>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &pat, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(pat, "\x015pattern");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_MODIFIER);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    FREE_STRING(st->ctx, pat);
+
+    pat = lydict_insert(st->ctx, "\006pattern", 8);
+    data = ELEMENT_WRAPPER_START "<modifier value=\"invert\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &pat, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"invert\" of \"value\" attribute in \"modifier\" element. Only valid value is \"invert-match\". Line number 1.");
+    FREE_STRING(st->ctx, pat);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_namespace_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    const char *ns;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<namespace uri=\"ns\">" EXT_SUBELEM "</namespace>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &ns, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(ns, "ns");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_NAMESPACE);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    FREE_STRING(st->ctx, ns);
+
+    data = ELEMENT_WRAPPER_START "<namespace/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &ns, NULL, NULL), LY_EVALID);
+    logbuf_assert("Missing mandatory attribute uri of namespace element. Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_path_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_type type = {};
+
+    data = ELEMENT_WRAPPER_START "<path value=\"p&amp;th-val\">" EXT_SUBELEM "</path>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_string_equal("p&th-val", type.path);
+    assert_true(type.flags & LYS_SET_PATH);
+    assert_string_equal(type.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(type.exts[0].insubstmt_index, 0);
+    assert_int_equal(type.exts[0].insubstmt, LYEXT_SUBSTMT_PATH);
+    lysp_type_free(st->ctx, &type);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_pattern_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_type type = {};
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<pattern value=\"super_pattern\">"
+                    "<modifier value=\"invert-match\"/>"
+                    "<error-message><value>err-msg-value</value></error-message>"
+                    "<error-app-tag value=\"err-app-tag-value\"/>"
+                    "<description><text>&quot;pattern-desc&quot;</text></description>"
+                    "<reference><text>pattern-ref</text></reference>"
+                    EXT_SUBELEM
+                "</pattern>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_true(type.flags & LYS_SET_PATTERN);
+    assert_string_equal(type.patterns->arg, "\x015super_pattern");
+    assert_string_equal(type.patterns->dsc, "\"pattern-desc\"");
+    assert_string_equal(type.patterns->eapptag, "err-app-tag-value");
+    assert_string_equal(type.patterns->emsg, "err-msg-value");
+    assert_string_equal(type.patterns->ref, "pattern-ref");
+    assert_string_equal(type.patterns->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(type.patterns->exts[0].insubstmt_index, 0);
+    assert_int_equal(type.patterns->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof(type));
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<pattern value=\"pattern\"> </pattern>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(type.patterns->arg, "\x006pattern");
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof(type));
+
+    st->finished_correctly = true;
+}
+
+static void
+test_value_position_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_type_enum en = {};
+
+    /* valid values */
+    data = ELEMENT_WRAPPER_START "<value value=\"55\">" EXT_SUBELEM "</value>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(en.value, 55);
+    assert_true(en.flags & LYS_SET_VALUE);
+    assert_string_equal(en.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(en.exts[0].insubstmt_index, 0);
+    assert_int_equal(en.exts[0].insubstmt, LYEXT_SUBSTMT_VALUE);
+    FREE_ARRAY(st->ctx, en.exts, lysp_ext_instance_free);
+    memset(&en, 0, sizeof(en));
+
+    data = ELEMENT_WRAPPER_START "<value value=\"-55\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(en.value, -55);
+    assert_true(en.flags & LYS_SET_VALUE);
+    memset(&en, 0, sizeof(en));
+
+    data = ELEMENT_WRAPPER_START "<value value=\"0\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(en.value, 0);
+    assert_true(en.flags & LYS_SET_VALUE);
+    memset(&en, 0, sizeof(en));
+
+    data = ELEMENT_WRAPPER_START "<value value=\"-0\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(en.value, 0);
+    assert_true(en.flags & LYS_SET_VALUE);
+    memset(&en, 0, sizeof(en));
+
+    /* valid positions */
+    data = ELEMENT_WRAPPER_START "<position value=\"55\">" EXT_SUBELEM "</position>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(en.value, 55);
+    assert_true(en.flags & LYS_SET_VALUE);
+    assert_string_equal(en.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(en.exts[0].insubstmt_index, 0);
+    assert_int_equal(en.exts[0].insubstmt, LYEXT_SUBSTMT_POSITION);
+    FREE_ARRAY(st->ctx, en.exts, lysp_ext_instance_free);
+    memset(&en, 0, sizeof(en));
+
+    data = ELEMENT_WRAPPER_START "<position value=\"0\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(en.value, 0);
+    assert_true(en.flags & LYS_SET_VALUE);
+    memset(&en, 0, sizeof(en));
+
+    /* invalid values */
+    data = ELEMENT_WRAPPER_START "<value value=\"99999999999999999999999\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"99999999999999999999999\" of \"value\" attribute in \"value\" element. Line number 1.");
+
+    data = ELEMENT_WRAPPER_START "<value value=\"1k\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"1k\" of \"value\" attribute in \"value\" element. Line number 1.");
+
+    data = ELEMENT_WRAPPER_START "<value value=\"\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"\" of \"value\" attribute in \"value\" element. Line number 1.");
+
+    /*invalid positions */
+    data = ELEMENT_WRAPPER_START "<position value=\"-5\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"-5\" of \"value\" attribute in \"position\" element. Line number 1.");
+
+    data = ELEMENT_WRAPPER_START "<position value=\"-0\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"-0\" of \"value\" attribute in \"position\" element. Line number 1.");
+
+    data = ELEMENT_WRAPPER_START "<position value=\"99999999999999999999\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"99999999999999999999\" of \"value\" attribute in \"position\" element. Line number 1.");
+
+    data = ELEMENT_WRAPPER_START "<position value=\"\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &en, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"\" of \"value\" attribute in \"position\" element. Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_prefix_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    const char *value = NULL;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<prefix value=\"pref\">" EXT_SUBELEM "</prefix>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &value, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(value, "pref");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_PREFIX);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    exts = NULL;
+    FREE_STRING(st->ctx, value);
+
+    data = ELEMENT_WRAPPER_START "<prefix value=\"pref\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &value, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(value, "pref");
+    FREE_STRING(st->ctx, value);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_range_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_type type = {};
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<range value=\"range-str\">"
+                    "<error-message><value>err-msg</value></error-message>"
+                    "<error-app-tag value=\"err-app-tag\" />"
+                    "<description><text>desc</text></description>"
+                    "<reference><text>ref</text></reference>"
+                    EXT_SUBELEM
+                "</range>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(type.range->arg, "range-str");
+    assert_string_equal(type.range->dsc, "desc");
+    assert_string_equal(type.range->eapptag, "err-app-tag");
+    assert_string_equal(type.range->emsg, "err-msg");
+    assert_string_equal(type.range->ref, "ref");
+    assert_true(type.flags & LYS_SET_RANGE);
+    assert_string_equal(type.range->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(type.range->exts[0].insubstmt_index, 0);
+    assert_int_equal(type.range->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof(type));
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<range value=\"range-str\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(type.range->arg, "range-str");
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof(type));
+
+    st->finished_correctly = true;
+}
+
+static void
+test_reqinstance_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_type type = {};
+
+    data = ELEMENT_WRAPPER_START "<require-instance value=\"true\">" EXT_SUBELEM "</require-instance>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(type.require_instance, 1);
+    assert_true(type.flags & LYS_SET_REQINST);
+    assert_string_equal(type.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(type.exts[0].insubstmt_index, 0);
+    assert_int_equal(type.exts[0].insubstmt, LYEXT_SUBSTMT_REQINSTANCE);
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof(type));
+
+    data = ELEMENT_WRAPPER_START "<require-instance value=\"false\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(type.require_instance, 0);
+    assert_true(type.flags & LYS_SET_REQINST);
+    memset(&type, 0, sizeof(type));
+
+    data = ELEMENT_WRAPPER_START "<require-instance value=\"invalid\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_EVALID);
+    memset(&type, 0, sizeof(type));
+    logbuf_assert("Invalid value \"invalid\" of \"value\" attribute in \"require-instance\" element. Valid values are \"true\" and \"false\". Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_revision_date_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    char rev[LY_REV_SIZE];
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<revision-date date=\"2000-01-01\">"EXT_SUBELEM"</revision-date>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, rev, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(rev, "2000-01-01");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_REVISIONDATE);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+
+    data = ELEMENT_WRAPPER_START "<revision-date date=\"2000-01-01\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, rev, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(rev, "2000-01-01");
+
+    data = ELEMENT_WRAPPER_START "<revision-date date=\"2000-50-05\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, rev, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"2000-50-05\" of \"revision-date\". Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_unique_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    const char **values = NULL;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<unique tag=\"tag\">"EXT_SUBELEM"</unique>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &values, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(*values, "tag");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_UNIQUE);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    FREE_STRING(st->ctx, *values);
+    LY_ARRAY_FREE(values);
+    values = NULL;
+
+    data = ELEMENT_WRAPPER_START "<unique tag=\"tag\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &values, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(*values, "tag");
+    FREE_STRING(st->ctx, *values);
+    LY_ARRAY_FREE(values);
+    values = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_units_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    const char *values = NULL;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<units name=\"name\">"EXT_SUBELEM"</units>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &values, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(values, "name");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_UNITS);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    FREE_STRING(st->ctx, values);
+    values = NULL;
+
+    data = ELEMENT_WRAPPER_START "<units name=\"name\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &values, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(values, "name");
+    FREE_STRING(st->ctx, values);
+    values = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_when_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_when *when = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<when condition=\"cond\">"
+                    "<description><text>desc</text></description>"
+                    "<reference><text>ref</text></reference>"
+                    EXT_SUBELEM
+                "</when>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &when, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(when->cond, "cond");
+    assert_string_equal(when->dsc, "desc");
+    assert_string_equal(when->ref, "ref");
+    assert_string_equal(when->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(when->exts[0].insubstmt_index, 0);
+    assert_int_equal(when->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_when_free(st->ctx, when);
+    free(when);
+    when = NULL;
+
+    data = ELEMENT_WRAPPER_START "<when condition=\"cond\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &when, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(when->cond, "cond");
+    lysp_when_free(st->ctx, when);
+    free(when);
+    when = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_yin_text_value_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    const char *val;
+
+    data = ELEMENT_WRAPPER_START "<text>text</text>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(val, "text");
+    FREE_STRING(st->ctx, val);
+
+    data = "<error-message xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <value>text</value> </error-message>";
+    assert_int_equal(test_element_helper(st, data, &val, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(val, "text");
+    FREE_STRING(st->ctx, val);
+
+    data = ELEMENT_WRAPPER_START "<text></text>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, NULL), LY_SUCCESS);
+    assert_string_equal("", val);
+    FREE_STRING(st->ctx, val);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_type_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_type type = {};
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<type name=\"type-name\">"
+                    "<base name=\"base-name\"/>"
+                    "<bit name=\"bit\"/>"
+                    "<enum name=\"enum\"/>"
+                    "<fraction-digits value=\"2\"/>"
+                    "<length value=\"length\"/>"
+                    "<path value=\"path\"/>"
+                    "<pattern value=\"pattern\"/>"
+                    "<range value=\"range\" />"
+                    "<require-instance value=\"true\"/>"
+                    "<type name=\"sub-type-name\"/>"
+                    EXT_SUBELEM
+                "</type>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(type.name, "type-name");
+    assert_string_equal(*type.bases, "base-name");
+    assert_string_equal(type.bits->name,  "bit");
+    assert_string_equal(type.enums->name,  "enum");
+    assert_int_equal(type.fraction_digits, 2);
+    assert_string_equal(type.length->arg, "length");
+    assert_string_equal(type.path, "path");
+    assert_string_equal(type.patterns->arg, "\006pattern");
+    assert_string_equal(type.range->arg, "range");
+    assert_int_equal(type.require_instance, 1);
+    assert_string_equal(type.types->name, "sub-type-name");
+    assert_string_equal(type.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(type.exts[0].insubstmt_index, 0);
+    assert_int_equal(type.exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    assert_true(type.flags & LYS_SET_BASE);
+    assert_true(type.flags & LYS_SET_BIT);
+    assert_true(type.flags & LYS_SET_ENUM);
+    assert_true(type.flags & LYS_SET_FRDIGITS);
+    assert_true(type.flags & LYS_SET_LENGTH);
+    assert_true(type.flags & LYS_SET_PATH);
+    assert_true(type.flags & LYS_SET_PATTERN);
+    assert_true(type.flags & LYS_SET_RANGE);
+    assert_true(type.flags & LYS_SET_REQINST);
+    assert_true(type.flags & LYS_SET_TYPE);
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof(type));
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<type name=\"type-name\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &type, NULL, NULL), LY_SUCCESS);
+    lysp_type_free(st->ctx, &type);
+    memset(&type, 0, sizeof(type));
+
+    st->finished_correctly = true;
+}
+
+static void
+test_max_elems_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_node_list list = {};
+    struct lysp_node_leaflist llist = {};
+    struct lysp_refine refine = {};
+
+    data = "<refine xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <max-elements value=\"unbounded\">"EXT_SUBELEM"</max-elements> </refine>";
+    assert_int_equal(test_element_helper(st, data, &refine, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(refine.max, 0);
+    assert_true(refine.flags & LYS_SET_MAX);
+    assert_string_equal(refine.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(refine.exts[0].insubstmt_index, 0);
+    assert_int_equal(refine.exts[0].insubstmt, LYEXT_SUBSTMT_MAX);
+    FREE_ARRAY(st->ctx, refine.exts, lysp_ext_instance_free);
+
+    data = "<list xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <max-elements value=\"5\">"EXT_SUBELEM"</max-elements> </list>";
+    assert_int_equal(test_element_helper(st, data, &list, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(list.max, 5);
+    assert_true(list.flags & LYS_SET_MAX);
+    assert_string_equal(list.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(list.exts[0].insubstmt_index, 0);
+    assert_int_equal(list.exts[0].insubstmt, LYEXT_SUBSTMT_MAX);
+    FREE_ARRAY(st->ctx, list.exts, lysp_ext_instance_free);
+
+    data = "<leaf-list xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <max-elements value=\"85\">"EXT_SUBELEM"</max-elements> </leaf-list>";
+    assert_int_equal(test_element_helper(st, data, &llist, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(llist.max, 85);
+    assert_true(llist.flags & LYS_SET_MAX);
+    assert_string_equal(llist.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(llist.exts[0].insubstmt_index, 0);
+    assert_int_equal(llist.exts[0].insubstmt, LYEXT_SUBSTMT_MAX);
+    FREE_ARRAY(st->ctx, llist.exts, lysp_ext_instance_free);
+
+    data = "<refine xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <max-elements value=\"10\"/> </refine>";
+    assert_int_equal(test_element_helper(st, data, &refine, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(refine.max, 10);
+    assert_true(refine.flags & LYS_SET_MAX);
+
+    data = "<list xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <max-elements value=\"0\"/> </list>";
+    assert_int_equal(test_element_helper(st, data, &list, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"0\" of \"value\" attribute in \"max-elements\" element. Line number 1.");
+
+    data = "<list xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <max-elements value=\"-10\"/> </list>";
+    assert_int_equal(test_element_helper(st, data, &list, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"-10\" of \"value\" attribute in \"max-elements\" element. Line number 1.");
+
+    data = "<list xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <max-elements value=\"k\"/> </list>";
+    assert_int_equal(test_element_helper(st, data, &list, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"k\" of \"value\" attribute in \"max-elements\" element. Line number 1.");
+
+    data = "<list xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <max-elements value=\"u12\"/> </list>";
+    assert_int_equal(test_element_helper(st, data, &list, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"u12\" of \"value\" attribute in \"max-elements\" element. Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_min_elems_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_node_list list = {};
+    struct lysp_node_leaflist llist = {};
+    struct lysp_refine refine = {};
+
+    data = "<refine xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <min-elements value=\"0\">"EXT_SUBELEM"</min-elements> </refine>";
+    assert_int_equal(test_element_helper(st, data, &refine, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(refine.min, 0);
+    assert_true(refine.flags & LYS_SET_MIN);
+    assert_string_equal(refine.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(refine.exts[0].insubstmt_index, 0);
+    assert_int_equal(refine.exts[0].insubstmt, LYEXT_SUBSTMT_MIN);
+    FREE_ARRAY(st->ctx, refine.exts, lysp_ext_instance_free);
+
+    data = "<list xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <min-elements value=\"41\">"EXT_SUBELEM"</min-elements> </list>";
+    assert_int_equal(test_element_helper(st, data, &list, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(list.min, 41);
+    assert_true(list.flags & LYS_SET_MIN);
+    assert_string_equal(list.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(list.exts[0].insubstmt_index, 0);
+    assert_int_equal(list.exts[0].insubstmt, LYEXT_SUBSTMT_MIN);
+    FREE_ARRAY(st->ctx, list.exts, lysp_ext_instance_free);
+
+    data = "<leaf-list xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <min-elements value=\"50\">"EXT_SUBELEM"</min-elements> </leaf-list>";
+    assert_int_equal(test_element_helper(st, data, &llist, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(llist.min, 50);
+    assert_true(llist.flags & LYS_SET_MIN);
+    assert_string_equal(llist.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(llist.exts[0].insubstmt_index, 0);
+    assert_int_equal(llist.exts[0].insubstmt, LYEXT_SUBSTMT_MIN);
+    FREE_ARRAY(st->ctx, llist.exts, lysp_ext_instance_free);
+
+    data = "<leaf-list xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <min-elements value=\"-5\"/> </leaf-list>";
+    assert_int_equal(test_element_helper(st, data, &llist, NULL, NULL), LY_EVALID);
+    logbuf_assert("Value \"-5\" of \"value\" attribute in \"min-elements\" element is out of bounds. Line number 1.");
+
+    data = "<leaf-list xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <min-elements value=\"99999999999999999\"/> </leaf-list>";
+    assert_int_equal(test_element_helper(st, data, &llist, NULL, NULL), LY_EVALID);
+    logbuf_assert("Value \"99999999999999999\" of \"value\" attribute in \"min-elements\" element is out of bounds. Line number 1.");
+
+    data = "<leaf-list xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <min-elements value=\"5k\"/> </leaf-list>";
+    assert_int_equal(test_element_helper(st, data, &llist, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"5k\" of \"value\" attribute in \"min-elements\" element. Line number 1.");
+
+    data = "<leaf-list xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"> <min-elements value=\"05\"/> </leaf-list>";
+    assert_int_equal(test_element_helper(st, data, &llist, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"05\" of \"value\" attribute in \"min-elements\" element. Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_ordby_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    uint16_t flags = 0;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<ordered-by value=\"system\">"EXT_SUBELEM"</ordered-by>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, &exts), LY_SUCCESS);
+    assert_true(flags & LYS_ORDBY_SYSTEM);
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_ORDEREDBY);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+
+    data = ELEMENT_WRAPPER_START "<ordered-by value=\"user\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, NULL), LY_SUCCESS);
+    assert_true(flags & LYS_ORDBY_USER);
+
+    data = ELEMENT_WRAPPER_START "<ordered-by value=\"inv\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &flags, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"inv\" of \"value\" attribute in \"ordered-by\" element. Valid values are \"system\" and \"user\". Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_any_elem(void **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};
+    struct lysp_node_anydata *parsed = NULL;
+
+    /* anyxml max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<anyxml name=\"any-name\">"
+                    "<config value=\"true\" />"
+                    "<description><text>desc</text></description>"
+                    "<if-feature name=\"feature\" />"
+                    "<mandatory value=\"true\" />"
+                    "<must condition=\"must-cond\" />"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"deprecated\"/>"
+                    "<when condition=\"when-cond\"/>"
+                    EXT_SUBELEM
+                "</anyxml>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_anydata *)siblings;
+    assert_null(parsed->parent);
+    assert_int_equal(parsed->nodetype, LYS_ANYXML);
+    assert_true(parsed->flags & LYS_CONFIG_W);
+    assert_true(parsed->flags & LYS_MAND_TRUE);
+    assert_true(parsed->flags & LYS_STATUS_DEPRC);
+    assert_null(parsed->next);
+    assert_string_equal(parsed->name, "any-name");
+    assert_string_equal(parsed->dsc, "desc");
+    assert_string_equal(parsed->ref, "ref");
+    assert_string_equal(parsed->when->cond, "when-cond");
+    assert_string_equal(*parsed->iffeatures, "feature");
+    assert_string_equal(parsed->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(parsed->exts[0].insubstmt_index, 0);
+    assert_int_equal(parsed->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    /* anydata max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<anydata name=\"any-name\">"
+                    "<config value=\"true\" />"
+                    "<description><text>desc</text></description>"
+                    "<if-feature name=\"feature\" />"
+                    "<mandatory value=\"true\" />"
+                    "<must condition=\"must-cond\" />"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"deprecated\"/>"
+                    "<when condition=\"when-cond\"/>"
+                    EXT_SUBELEM
+                "</anydata>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_anydata *)siblings;
+    assert_null(parsed->parent);
+    assert_int_equal(parsed->nodetype, LYS_ANYDATA);
+    assert_true(parsed->flags & LYS_CONFIG_W);
+    assert_true(parsed->flags & LYS_MAND_TRUE);
+    assert_true(parsed->flags & LYS_STATUS_DEPRC);
+    assert_null(parsed->next);
+    assert_string_equal(parsed->name, "any-name");
+    assert_string_equal(parsed->dsc, "desc");
+    assert_string_equal(parsed->ref, "ref");
+    assert_string_equal(parsed->when->cond, "when-cond");
+    assert_string_equal(*parsed->iffeatures, "feature");
+    assert_string_equal(parsed->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(parsed->exts[0].insubstmt_index, 0);
+    assert_int_equal(parsed->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    /* min subelems */
+    node_meta.parent = (void *)0x10;
+    data = ELEMENT_WRAPPER_START "<anydata name=\"any-name\"> </anydata>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_anydata *)siblings;
+    assert_ptr_equal(parsed->parent, node_meta.parent);
+    assert_int_equal(parsed->nodetype, LYS_ANYDATA);
+    assert_null(parsed->next);
+    assert_null(parsed->exts);
+    lysp_node_free(st->ctx, siblings);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_leaf_elem(void **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};
+    struct lysp_node_leaf *parsed = NULL;
+
+    /* max elements */
+    data = ELEMENT_WRAPPER_START
+                "<leaf name=\"leaf\">"
+                    "<config value=\"true\" />"
+                    "<default value=\"def-val\"/>"
+                    "<description><text>desc</text></description>"
+                    "<if-feature name=\"feature\" />"
+                    "<mandatory value=\"true\" />"
+                    "<must condition=\"must-cond\" />"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"deprecated\"/>"
+                    "<type name=\"type\"/>"
+                    "<units name=\"uni\"/>"
+                    "<when condition=\"when-cond\"/>"
+                    EXT_SUBELEM
+                "</leaf>"
+            ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_leaf *)siblings;
+    assert_null(parsed->parent);
+    assert_int_equal(parsed->nodetype, LYS_LEAF);
+    assert_true(parsed->flags & LYS_CONFIG_W);
+    assert_true(parsed->flags & LYS_MAND_TRUE);
+    assert_true(parsed->flags & LYS_STATUS_DEPRC);
+    assert_null(parsed->next);
+    assert_string_equal(parsed->name, "leaf");
+    assert_string_equal(parsed->dsc, "desc");
+    assert_string_equal(parsed->ref, "ref");
+    assert_string_equal(parsed->when->cond, "when-cond");
+    assert_string_equal(*parsed->iffeatures, "feature");
+    assert_string_equal(parsed->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(parsed->exts[0].insubstmt_index, 0);
+    assert_int_equal(parsed->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    assert_string_equal(parsed->musts->arg, "must-cond");
+    assert_string_equal(parsed->type.name, "type");
+    assert_string_equal(parsed->units, "uni");
+    assert_string_equal(parsed->dflt, "def-val");
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    /* min elements */
+    data = ELEMENT_WRAPPER_START "<leaf name=\"leaf\"> <type name=\"type\"/> </leaf>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_leaf *)siblings;
+    assert_string_equal(parsed->name, "leaf");
+    assert_string_equal(parsed->type.name, "type");
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_leaf_list_elem(void **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};
+    struct lysp_node_leaflist *parsed = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<leaf-list name=\"llist\">"
+                    "<config value=\"true\" />"
+                    "<default value=\"def-val0\"/>"
+                    "<default value=\"def-val1\"/>"
+                    "<description><text>desc</text></description>"
+                    "<if-feature name=\"feature\"/>"
+                    "<max-elements value=\"5\"/>"
+                    "<must condition=\"must-cond\"/>"
+                    "<ordered-by value=\"user\" />"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"current\"/>"
+                    "<type name=\"type\"/>"
+                    "<units name=\"uni\"/>"
+                    "<when condition=\"when-cond\"/>"
+                    EXT_SUBELEM
+                "</leaf-list>"
+            ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_leaflist *)siblings;
+    assert_string_equal(parsed->dflts[0], "def-val0");
+    assert_string_equal(parsed->dflts[1], "def-val1");
+    assert_string_equal(parsed->dsc, "desc");
+    assert_string_equal(*parsed->iffeatures, "feature");
+    assert_int_equal(parsed->max, 5);
+    assert_string_equal(parsed->musts->arg, "must-cond");
+    assert_string_equal(parsed->name, "llist");
+    assert_null(parsed->next);
+    assert_int_equal(parsed->nodetype, LYS_LEAFLIST);
+    assert_null(parsed->parent);
+    assert_string_equal(parsed->ref, "ref");
+    assert_string_equal(parsed->type.name, "type");
+    assert_string_equal(parsed->units, "uni");
+    assert_string_equal(parsed->when->cond, "when-cond");
+    assert_true(parsed->flags & LYS_CONFIG_W);
+    assert_true(parsed->flags & LYS_ORDBY_USER);
+    assert_true(parsed->flags & LYS_STATUS_CURR);
+    assert_string_equal(parsed->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(parsed->exts[0].insubstmt_index, 0);
+    assert_int_equal(parsed->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<leaf-list name=\"llist\">"
+                    "<config value=\"true\" />"
+                    "<description><text>desc</text></description>"
+                    "<if-feature name=\"feature\"/>"
+                    "<min-elements value=\"5\"/>"
+                    "<must condition=\"must-cond\"/>"
+                    "<ordered-by value=\"user\" />"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"current\"/>"
+                    "<type name=\"type\"/>"
+                    "<units name=\"uni\"/>"
+                    "<when condition=\"when-cond\"/>"
+                    EXT_SUBELEM
+                "</leaf-list>"
+            ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_leaflist *)siblings;
+    assert_string_equal(parsed->dsc, "desc");
+    assert_string_equal(*parsed->iffeatures, "feature");
+    assert_int_equal(parsed->min, 5);
+    assert_string_equal(parsed->musts->arg, "must-cond");
+    assert_string_equal(parsed->name, "llist");
+    assert_null(parsed->next);
+    assert_int_equal(parsed->nodetype, LYS_LEAFLIST);
+    assert_null(parsed->parent);
+    assert_string_equal(parsed->ref, "ref");
+    assert_string_equal(parsed->type.name, "type");
+    assert_string_equal(parsed->units, "uni");
+    assert_string_equal(parsed->when->cond, "when-cond");
+    assert_true(parsed->flags & LYS_CONFIG_W);
+    assert_true(parsed->flags & LYS_ORDBY_USER);
+    assert_true(parsed->flags & LYS_STATUS_CURR);
+    assert_string_equal(parsed->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(parsed->exts[0].insubstmt_index, 0);
+    assert_int_equal(parsed->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<leaf-list name=\"llist\">"
+                    "<config value=\"true\" />"
+                    "<description><text>desc</text></description>"
+                    "<if-feature name=\"feature\"/>"
+                    "<max-elements value=\"15\"/>"
+                    "<min-elements value=\"5\"/>"
+                    "<must condition=\"must-cond\"/>"
+                    "<ordered-by value=\"user\" />"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"current\"/>"
+                    "<type name=\"type\"/>"
+                    "<units name=\"uni\"/>"
+                    "<when condition=\"when-cond\"/>"
+                "</leaf-list>"
+            ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_leaflist *)siblings;
+    assert_string_equal(parsed->dsc, "desc");
+    assert_string_equal(*parsed->iffeatures, "feature");
+    assert_int_equal(parsed->min, 5);
+    assert_int_equal(parsed->max, 15);
+    assert_string_equal(parsed->musts->arg, "must-cond");
+    assert_string_equal(parsed->name, "llist");
+    assert_null(parsed->next);
+    assert_int_equal(parsed->nodetype, LYS_LEAFLIST);
+    assert_null(parsed->parent);
+    assert_string_equal(parsed->ref, "ref");
+    assert_string_equal(parsed->type.name, "type");
+    assert_string_equal(parsed->units, "uni");
+    assert_string_equal(parsed->when->cond, "when-cond");
+    assert_true(parsed->flags & LYS_CONFIG_W);
+    assert_true(parsed->flags & LYS_ORDBY_USER);
+    assert_true(parsed->flags & LYS_STATUS_CURR);
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<leaf-list name=\"llist\">"
+                    "<type name=\"type\"/>"
+                "</leaf-list>"
+            ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_leaflist *)siblings;
+    assert_string_equal(parsed->name, "llist");
+    assert_string_equal(parsed->type.name, "type");
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    /* invalid combinations */
+    data = ELEMENT_WRAPPER_START
+                "<leaf-list name=\"llist\">"
+                    "<max-elements value=\"5\"/>"
+                    "<min-elements value=\"15\"/>"
+                    "<type name=\"type\"/>"
+                "</leaf-list>"
+            ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid combination of min-elements and max-elements: min value 15 is bigger than the max value 5. Line number 1.");
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<leaf-list name=\"llist\">"
+                    "<default value=\"def-val1\"/>"
+                    "<min-elements value=\"15\"/>"
+                    "<type name=\"type\"/>"
+                "</leaf-list>"
+            ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid combination of sub-elemnts \"min-elements\" and \"default\" in \"leaf-list\" element. Line number 1.");
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<leaf-list name=\"llist\">"
+                "</leaf-list>"
+            ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_EVALID);
+    logbuf_assert("Missing mandatory sub-element \"type\" of \"leaf-list\" element. Line number 1.");
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_presence_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    const char *val;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<presence value=\"presence-val\">"EXT_SUBELEM"</presence>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(val, "presence-val");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_PRESENCE);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    FREE_STRING(st->ctx, val);
+
+    data = ELEMENT_WRAPPER_START "<presence value=\"presence-val\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(val, "presence-val");
+    FREE_STRING(st->ctx, val);
+
+    data = ELEMENT_WRAPPER_START "<presence/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, NULL), LY_EVALID);
+    logbuf_assert("Missing mandatory attribute value of presence element. Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_key_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    const char *val;
+    struct lysp_ext_instance *exts = NULL;
+
+    data = ELEMENT_WRAPPER_START "<key value=\"key-value\">"EXT_SUBELEM"</key>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, &exts), LY_SUCCESS);
+    assert_string_equal(val, "key-value");
+    assert_string_equal(exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(exts[0].insubstmt_index, 0);
+    assert_int_equal(exts[0].insubstmt, LYEXT_SUBSTMT_KEY);
+    FREE_ARRAY(st->ctx, exts, lysp_ext_instance_free);
+    FREE_STRING(st->ctx, val);
+
+    data = ELEMENT_WRAPPER_START "<key value=\"key-value\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(val, "key-value");
+    FREE_STRING(st->ctx, val);
+
+    data = ELEMENT_WRAPPER_START "<key/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &val, NULL, NULL), LY_EVALID);
+    logbuf_assert("Missing mandatory attribute value of key element. Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_typedef_elem(void **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};
+
+    data = ELEMENT_WRAPPER_START
+                "<typedef name=\"tpdf-name\">"
+                    "<default value=\"def-val\"/>"
+                    "<description><text>desc-text</text></description>"
+                    "<reference><text>ref-text</text></reference>"
+                    "<status value=\"current\"/>"
+                    "<type name=\"type\"/>"
+                    "<units name=\"uni\"/>"
+                    EXT_SUBELEM
+                "</typedef>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &typdef_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(tpdfs[0].dflt, "def-val");
+    assert_string_equal(tpdfs[0].dsc, "desc-text");
+    assert_string_equal(tpdfs[0].name, "tpdf-name");
+    assert_string_equal(tpdfs[0].ref, "ref-text");
+    assert_string_equal(tpdfs[0].type.name, "type");
+    assert_string_equal(tpdfs[0].units, "uni");
+    assert_true(tpdfs[0].flags & LYS_STATUS_CURR);
+    assert_string_equal(tpdfs[0].exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(tpdfs[0].exts[0].insubstmt_index, 0);
+    assert_int_equal(tpdfs[0].exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    FREE_ARRAY(st->ctx, tpdfs, lysp_tpdf_free);
+    tpdfs = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<typedef name=\"tpdf-name\">"
+                    "<type name=\"type\"/>"
+                "</typedef>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &typdef_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(tpdfs[0].name, "tpdf-name");
+    assert_string_equal(tpdfs[0].type.name, "type");
+    FREE_ARRAY(st->ctx, tpdfs, lysp_tpdf_free);
+    tpdfs = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_refine_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_refine *refines = NULL;
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<refine target-node=\"target\">"
+                    "<if-feature name=\"feature\" />"
+                    "<must condition=\"cond\" />"
+                    "<presence value=\"presence\" />"
+                    "<default value=\"def\" />"
+                    "<config value=\"true\" />"
+                    "<mandatory value=\"true\" />"
+                    "<min-elements value=\"10\" />"
+                    "<max-elements value=\"20\" />"
+                    "<description><text>desc</text></description>"
+                    "<reference><text>ref</text></reference>"
+                    EXT_SUBELEM
+                "</refine>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &refines, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(refines->nodeid, "target");
+    assert_string_equal(*refines->dflts, "def");
+    assert_string_equal(refines->dsc, "desc");
+    assert_true(refines->flags & LYS_CONFIG_W);
+    assert_true(refines->flags & LYS_MAND_TRUE);
+    assert_string_equal(*refines->iffeatures, "feature");
+    assert_int_equal(refines->max, 20);
+    assert_int_equal(refines->min, 10);
+    assert_string_equal(refines->musts->arg, "cond");
+    assert_string_equal(refines->presence, "presence");
+    assert_string_equal(refines->ref, "ref");
+    assert_string_equal(refines->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(refines->exts[0].insubstmt_index, 0);
+    assert_int_equal(refines->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    FREE_ARRAY(st->ctx, refines, lysp_refine_free);
+    refines = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<refine target-node=\"target\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &refines, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(refines->nodeid, "target");
+    FREE_ARRAY(st->ctx, refines, lysp_refine_free);
+    refines = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_uses_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_node *siblings = NULL;
+    struct tree_node_meta node_meta = {NULL, &siblings};
+    struct lysp_node_uses *parsed = NULL;
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<uses name=\"uses-name\">"
+                    "<when condition=\"cond\" />"
+                    "<if-feature name=\"feature\" />"
+                    "<status value=\"obsolete\" />"
+                    "<description><text>desc</text></description>"
+                    "<reference><text>ref</text></reference>"
+                    "<refine target-node=\"target\"/>"
+                    "<augment target-node=\"target\" />"
+                    EXT_SUBELEM
+                "</uses>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_uses *)&siblings[0];
+    assert_string_equal(parsed->name, "uses-name");
+    assert_string_equal(parsed->dsc, "desc");
+    assert_true(parsed->flags & LYS_STATUS_OBSLT);
+    assert_string_equal(*parsed->iffeatures, "feature");
+    assert_null(parsed->next);
+    assert_int_equal(parsed->nodetype, LYS_USES);
+    assert_null(parsed->parent);
+    assert_string_equal(parsed->ref, "ref");
+    assert_string_equal(parsed->refines->nodeid, "target");
+    assert_string_equal(parsed->when->cond, "cond");
+    assert_string_equal(parsed->augments->nodeid, "target");
+    assert_string_equal(parsed->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(parsed->exts[0].insubstmt_index, 0);
+    assert_int_equal(parsed->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<uses name=\"uses-name\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(siblings[0].name, "uses-name");
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_revision_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_revision *revs = NULL;
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<revision date=\"2018-12-25\">"
+                    "<description><text>desc</text></description>"
+                    "<reference><text>ref</text></reference>"
+                    EXT_SUBELEM
+                "</revision>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &revs, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(revs->date, "2018-12-25");
+    assert_string_equal(revs->dsc, "desc");
+    assert_string_equal(revs->ref, "ref");
+    assert_string_equal(revs->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(revs->exts[0].insubstmt_index, 0);
+    assert_int_equal(revs->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    FREE_ARRAY(st->ctx, revs, lysp_revision_free);
+    revs = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<revision date=\"2005-05-05\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &revs, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(revs->date, "2005-05-05");
+    FREE_ARRAY(st->ctx, revs, lysp_revision_free);
+    revs = NULL;
+
+    /* invalid value */
+    data = ELEMENT_WRAPPER_START "<revision date=\"05-05-2005\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &revs, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"05-05-2005\" of \"revision\". Line number 1.");
+    FREE_ARRAY(st->ctx, revs, lysp_revision_free);
+    revs = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_include_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_include *includes = NULL;
+    struct include_meta inc_meta = {"module-name", &includes};
+
+    /* max subelems */
+    st->yin_ctx->mod_version = LYS_VERSION_1_1;
+    data = ELEMENT_WRAPPER_START
+                "<include module=\"mod\">"
+                    "<description><text>desc</text></description>"
+                    "<reference><text>ref</text></reference>"
+                    "<revision-date date=\"1999-09-09\"/>"
+                    EXT_SUBELEM
+                "</include>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &inc_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(includes->name, "mod");
+    assert_string_equal(includes->dsc, "desc");
+    assert_string_equal(includes->ref, "ref");
+    assert_string_equal(includes->rev, "1999-09-09");
+    assert_string_equal(includes->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(includes->exts[0].insubstmt_index, 0);
+    assert_int_equal(includes->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    FREE_ARRAY(st->ctx, includes, lysp_include_free);
+    includes = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<include module=\"mod\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &inc_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(includes->name, "mod");
+    FREE_ARRAY(st->ctx, includes, lysp_include_free);
+    includes = NULL;
+
+    /* invalid combinations */
+    st->yin_ctx->mod_version = LYS_VERSION_1_0;
+    data = ELEMENT_WRAPPER_START
+                "<include module=\"mod\">"
+                    "<description><text>desc</text></description>"
+                    "<revision-date date=\"1999-09-09\"/>"
+                "</include>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &inc_meta, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid sub-elemnt \"description\" of \"include\" element - this sub-element is allowed only in modules with version 1.1 or newer. Line number 1.");
+    FREE_ARRAY(st->ctx, includes, lysp_include_free);
+    includes = NULL;
+
+    st->yin_ctx->mod_version = LYS_VERSION_1_0;
+    data = ELEMENT_WRAPPER_START
+                "<include module=\"mod\">"
+                    "<reference><text>ref</text></reference>"
+                    "<revision-date date=\"1999-09-09\"/>"
+                "</include>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &inc_meta, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid sub-elemnt \"reference\" of \"include\" element - this sub-element is allowed only in modules with version 1.1 or newer. Line number 1.");
+    FREE_ARRAY(st->ctx, includes, lysp_include_free);
+    includes = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_list_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_node *siblings = NULL;
+    struct tree_node_meta node_meta = {NULL, &siblings};
+    struct lysp_node_list *parsed = NULL;
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<list name=\"list-name\">"
+                    "<when condition=\"when\"/>"
+                    "<if-feature name=\"iff\"/>"
+                    "<must condition=\"must-cond\"/>"
+                    "<key value=\"key\"/>"
+                    "<unique tag=\"utag\"/>"
+                    "<config value=\"true\"/>"
+                    "<min-elements value=\"10\"/>"
+                    "<ordered-by value=\"user\"/>"
+                    "<status value=\"deprecated\"/>"
+                    "<description><text>desc</text></description>"
+                    "<reference><text>ref</text></reference>"
+                    "<anydata name=\"anyd\"/>"
+                    "<anyxml name=\"anyx\"/>"
+                    "<container name=\"cont\"/>"
+                    "<choice name=\"choice\"/>"
+                    "<action name=\"action\"/>"
+                    "<grouping name=\"grp\"/>"
+                    "<notification name=\"notf\"/>"
+                    "<leaf name=\"leaf\"> <type name=\"type\"/> </leaf>"
+                    "<leaf-list name=\"llist\"> <type name=\"type\"/> </leaf-list>"
+                    "<list name=\"sub-list\"/>"
+                    "<typedef name=\"tpdf\"> <type name=\"type\"/> </typedef>"
+                    "<uses name=\"uses-name\"/>"
+                    EXT_SUBELEM
+                "</list>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_list *)&siblings[0];
+    assert_string_equal(parsed->dsc, "desc");
+    assert_string_equal(parsed->child->name, "anyd");
+    assert_int_equal(parsed->child->nodetype, LYS_ANYDATA);
+    assert_string_equal(parsed->child->next->name, "anyx");
+    assert_int_equal(parsed->child->next->nodetype, LYS_ANYXML);
+    assert_string_equal(parsed->child->next->next->name, "cont");
+    assert_int_equal(parsed->child->next->next->nodetype, LYS_CONTAINER);
+    assert_string_equal(parsed->child->next->next->next->name, "choice");
+    assert_int_equal(parsed->child->next->next->next->nodetype, LYS_CHOICE);
+    assert_string_equal(parsed->child->next->next->next->next->name, "leaf");
+    assert_int_equal(parsed->child->next->next->next->next->nodetype, LYS_LEAF);
+    assert_string_equal(parsed->child->next->next->next->next->next->name, "llist");
+    assert_int_equal(parsed->child->next->next->next->next->next->nodetype, LYS_LEAFLIST);
+    assert_string_equal(parsed->child->next->next->next->next->next->next->name, "sub-list");
+    assert_int_equal(parsed->child->next->next->next->next->next->next->nodetype, LYS_LIST);
+    assert_string_equal(parsed->child->next->next->next->next->next->next->next->name, "uses-name");
+    assert_int_equal(parsed->child->next->next->next->next->next->next->next->nodetype, LYS_USES);
+    assert_null(parsed->child->next->next->next->next->next->next->next->next);
+    assert_string_equal(parsed->groupings->name, "grp");
+    assert_string_equal(parsed->actions->name, "action");
+    assert_int_equal(parsed->groupings->nodetype, LYS_GROUPING);
+    assert_string_equal(parsed->notifs->name, "notf");
+    assert_true(parsed->flags & LYS_ORDBY_USER);
+    assert_true(parsed->flags & LYS_STATUS_DEPRC);
+    assert_true(parsed->flags & LYS_CONFIG_W);
+    assert_string_equal(*parsed->iffeatures, "iff");
+    assert_string_equal(parsed->key, "key");
+    assert_int_equal(parsed->min, 10);
+    assert_string_equal(parsed->musts->arg, "must-cond");
+    assert_string_equal(parsed->name, "list-name");
+    assert_null(parsed->next);
+    assert_int_equal(parsed->nodetype, LYS_LIST);
+    assert_null(parsed->parent);
+    assert_string_equal(parsed->ref, "ref");
+    assert_string_equal(parsed->typedefs->name, "tpdf");
+    assert_string_equal(*parsed->uniques, "utag");
+    assert_string_equal(parsed->when->cond, "when");
+    assert_string_equal(parsed->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(parsed->exts[0].insubstmt_index, 0);
+    assert_int_equal(parsed->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_node_free(st->ctx, siblings);
+    ly_set_erase(&st->yin_ctx->tpdfs_nodes, NULL);
+    siblings = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<list name=\"list-name\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_list *)&siblings[0];
+    assert_string_equal(parsed->name, "list-name");
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_notification_elem(void **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};
+
+    /* max subelems */
+    st->yin_ctx->mod_version = LYS_VERSION_1_1;
+    data = ELEMENT_WRAPPER_START
+                "<notification name=\"notif-name\">"
+                    "<anydata name=\"anyd\"/>"
+                    "<anyxml name=\"anyx\"/>"
+                    "<description><text>desc</text></description>"
+                    "<if-feature name=\"iff\"/>"
+                    "<leaf name=\"leaf\"> <type name=\"type\"/> </leaf>"
+                    "<leaf-list name=\"llist\"> <type name=\"type\"/> </leaf-list>"
+                    "<list name=\"sub-list\"/>"
+                    "<must condition=\"cond\"/>"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"deprecated\"/>"
+                    "<typedef name=\"tpdf\"> <type name=\"type\"/> </typedef>"
+                    "<uses name=\"uses-name\"/>"
+                    "<container name=\"cont\"/>"
+                    "<choice name=\"choice\"/>"
+                    "<grouping name=\"grp\"/>"
+                    EXT_SUBELEM
+                "</notification>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &notif_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(notifs->name, "notif-name");
+    assert_string_equal(notifs->data->name, "anyd");
+    assert_int_equal(notifs->data->nodetype, LYS_ANYDATA);
+    assert_string_equal(notifs->data->next->name, "anyx");
+    assert_int_equal(notifs->data->next->nodetype, LYS_ANYXML);
+    assert_string_equal(notifs->data->next->next->name, "leaf");
+    assert_int_equal(notifs->data->next->next->nodetype, LYS_LEAF);
+    assert_string_equal(notifs->data->next->next->next->name, "llist");
+    assert_int_equal(notifs->data->next->next->next->nodetype, LYS_LEAFLIST);
+    assert_string_equal(notifs->data->next->next->next->next->name, "sub-list");
+    assert_int_equal(notifs->data->next->next->next->next->nodetype, LYS_LIST);
+    assert_true(notifs->flags & LYS_STATUS_DEPRC);
+    assert_string_equal(notifs->groupings->name, "grp");
+    assert_int_equal(notifs->groupings->nodetype, LYS_GROUPING);
+    assert_string_equal(notifs->data->next->next->next->next->next->name, "uses-name");
+    assert_int_equal(notifs->data->next->next->next->next->next->nodetype, LYS_USES);
+    assert_string_equal(notifs->data->next->next->next->next->next->next->name, "cont");
+    assert_int_equal(notifs->data->next->next->next->next->next->next->nodetype, LYS_CONTAINER);
+    assert_int_equal(notifs->data->next->next->next->next->next->next->next->nodetype, LYS_CHOICE);
+    assert_string_equal(notifs->data->next->next->next->next->next->next->next->name, "choice");
+    assert_null(notifs->data->next->next->next->next->next->next->next->next);
+    assert_string_equal(*notifs->iffeatures, "iff");
+    assert_string_equal(notifs->musts->arg, "cond");
+    assert_int_equal(notifs->nodetype, LYS_NOTIF);
+    assert_null(notifs->parent);
+    assert_string_equal(notifs->ref, "ref");
+    assert_string_equal(notifs->typedefs->name, "tpdf");
+    assert_string_equal(notifs->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(notifs->exts[0].insubstmt_index, 0);
+    assert_int_equal(notifs->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    FREE_ARRAY(st->ctx, notifs, lysp_notif_free);
+    notifs = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<notification name=\"notif-name\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &notif_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(notifs->name, "notif-name");
+    FREE_ARRAY(st->ctx, notifs, lysp_notif_free);
+    notifs = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_grouping_elem(void **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};
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<grouping name=\"grp-name\">"
+                    "<anydata name=\"anyd\"/>"
+                    "<anyxml name=\"anyx\"/>"
+                    "<description><text>desc</text></description>"
+                    "<grouping name=\"sub-grp\"/>"
+                    "<leaf name=\"leaf\"> <type name=\"type\"/> </leaf>"
+                    "<leaf-list name=\"llist\"> <type name=\"type\"/> </leaf-list>"
+                    "<list name=\"list\"/>"
+                    "<notification name=\"notf\"/>"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"current\"/>"
+                    "<typedef name=\"tpdf\"> <type name=\"type\"/> </typedef>"
+                    "<uses name=\"uses-name\"/>"
+                    "<action name=\"act\"/>"
+                    "<container name=\"cont\"/>"
+                    "<choice name=\"choice\"/>"
+                    EXT_SUBELEM
+                "</grouping>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &grp_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(grps->name, "grp-name");
+    assert_string_equal(grps->data->name, "anyd");
+    assert_string_equal(grps->data->next->name, "anyx");
+    assert_string_equal(grps->data->next->next->name, "leaf");
+    assert_string_equal(grps->data->next->next->next->name, "llist");
+    assert_string_equal(grps->data->next->next->next->next->name, "list");
+    assert_string_equal(grps->dsc, "desc");
+    assert_true(grps->flags & LYS_STATUS_CURR);
+    assert_string_equal(grps->groupings->name, "sub-grp");
+    assert_int_equal(grps->nodetype, LYS_GROUPING);
+    assert_string_equal(grps->notifs->name, "notf");
+    assert_null(grps->parent);
+    assert_string_equal(grps->ref, "ref");
+    assert_string_equal(grps->typedefs->name, "tpdf");
+    assert_string_equal(grps->actions->name, "act");
+    assert_string_equal(grps->data->next->next->next->next->next->name, "uses-name");
+    assert_int_equal(grps->data->next->next->next->next->next->nodetype, LYS_USES);
+    assert_string_equal(grps->data->next->next->next->next->next->next->name, "cont");
+    assert_int_equal(grps->data->next->next->next->next->next->next->nodetype, LYS_CONTAINER);
+    assert_string_equal(grps->data->next->next->next->next->next->next->next->name, "choice");
+    assert_int_equal(grps->data->next->next->next->next->next->next->next->nodetype, LYS_CHOICE);
+    assert_string_equal(grps->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(grps->exts[0].insubstmt_index, 0);
+    assert_int_equal(grps->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    FREE_ARRAY(st->ctx, grps, lysp_grp_free);
+    grps = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<grouping name=\"grp-name\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &grp_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(grps->name, "grp-name");
+    FREE_ARRAY(st->ctx, grps, lysp_grp_free);
+    grps = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_container_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_node *siblings = NULL;
+    struct tree_node_meta node_meta = {NULL, &siblings};
+    struct lysp_node_container *parsed = NULL;
+
+    /* max subelems */
+    st->yin_ctx->mod_version = LYS_VERSION_1_1;
+    data = ELEMENT_WRAPPER_START
+                "<container name=\"cont-name\">"
+                    "<anydata name=\"anyd\"/>"
+                    "<anyxml name=\"anyx\"/>"
+                    "<config value=\"true\"/>"
+                    "<container name=\"subcont\"/>"
+                    "<description><text>desc</text></description>"
+                    "<grouping name=\"sub-grp\"/>"
+                    "<if-feature name=\"iff\"/>"
+                    "<leaf name=\"leaf\"> <type name=\"type\"/> </leaf>"
+                    "<leaf-list name=\"llist\"> <type name=\"type\"/> </leaf-list>"
+                    "<list name=\"list\"/>"
+                    "<must condition=\"cond\"/>"
+                    "<notification name=\"notf\"/>"
+                    "<presence value=\"presence\"/>"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"current\"/>"
+                    "<typedef name=\"tpdf\"> <type name=\"type\"/> </typedef>"
+                    "<uses name=\"uses-name\"/>"
+                    "<when condition=\"when-cond\"/>"
+                    "<action name=\"act\"/>"
+                    "<choice name=\"choice\"/>"
+                    EXT_SUBELEM
+                "</container>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_container *)siblings;
+    assert_string_equal(parsed->name, "cont-name");
+    assert_null(parsed->parent);
+    assert_int_equal(parsed->nodetype, LYS_CONTAINER);
+    assert_true(parsed->flags & LYS_CONFIG_W);
+    assert_true(parsed->flags & LYS_STATUS_CURR);
+    assert_null(parsed->next);
+    assert_string_equal(parsed->dsc, "desc");
+    assert_string_equal(parsed->ref, "ref");
+    assert_string_equal(parsed->when->cond, "when-cond");
+    assert_string_equal(*parsed->iffeatures, "iff");
+    assert_string_equal(parsed->musts->arg, "cond");
+    assert_string_equal(parsed->presence, "presence");
+    assert_string_equal(parsed->typedefs->name, "tpdf");
+    assert_string_equal(parsed->groupings->name, "sub-grp");
+    assert_string_equal(parsed->child->name, "anyd");
+    assert_int_equal(parsed->child->nodetype, LYS_ANYDATA);
+    assert_string_equal(parsed->child->next->name, "anyx");
+    assert_int_equal(parsed->child->next->nodetype, LYS_ANYXML);
+    assert_string_equal(parsed->child->next->next->name, "subcont");
+    assert_int_equal(parsed->child->next->next->nodetype, LYS_CONTAINER);
+    assert_string_equal(parsed->child->next->next->next->name, "leaf");
+    assert_int_equal(parsed->child->next->next->next->nodetype, LYS_LEAF);
+    assert_string_equal(parsed->child->next->next->next->next->name, "llist");
+    assert_int_equal(parsed->child->next->next->next->next->nodetype, LYS_LEAFLIST);
+    assert_string_equal(parsed->child->next->next->next->next->next->name, "list");
+    assert_int_equal(parsed->child->next->next->next->next->next->nodetype, LYS_LIST);
+    assert_string_equal(parsed->child->next->next->next->next->next->next->name, "uses-name");
+    assert_int_equal(parsed->child->next->next->next->next->next->next->nodetype, LYS_USES);
+    assert_string_equal(parsed->child->next->next->next->next->next->next->next->name, "choice");
+    assert_int_equal(parsed->child->next->next->next->next->next->next->next->nodetype, LYS_CHOICE);
+    assert_null(parsed->child->next->next->next->next->next->next->next->next);
+    assert_string_equal(parsed->notifs->name, "notf");
+    assert_string_equal(parsed->actions->name, "act");
+    assert_string_equal(parsed->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(parsed->exts[0].insubstmt_index, 0);
+    assert_int_equal(parsed->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_node_free(st->ctx, siblings);
+    ly_set_erase(&st->yin_ctx->tpdfs_nodes, NULL);
+    siblings = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<container name=\"cont-name\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_container *)siblings;
+    assert_string_equal(parsed->name, "cont-name");
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_case_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_node *siblings = NULL;
+    struct tree_node_meta node_meta = {NULL, &siblings};
+    struct lysp_node_case *parsed = NULL;
+
+    /* max subelems */
+    st->yin_ctx->mod_version = LYS_VERSION_1_1;
+    data = ELEMENT_WRAPPER_START
+                "<case name=\"case-name\">"
+                    "<anydata name=\"anyd\"/>"
+                    "<anyxml name=\"anyx\"/>"
+                    "<container name=\"subcont\"/>"
+                    "<description><text>desc</text></description>"
+                    "<if-feature name=\"iff\"/>"
+                    "<leaf name=\"leaf\"> <type name=\"type\"/> </leaf>"
+                    "<leaf-list name=\"llist\"> <type name=\"type\"/> </leaf-list>"
+                    "<list name=\"list\"/>"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"current\"/>"
+                    "<uses name=\"uses-name\"/>"
+                    "<when condition=\"when-cond\"/>"
+                    "<choice name=\"choice\"/>"
+                    EXT_SUBELEM
+                "</case>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_case *)siblings;
+    assert_string_equal(parsed->name, "case-name");
+    assert_null(parsed->parent);
+    assert_int_equal(parsed->nodetype, LYS_CASE);
+    assert_true(parsed->flags & LYS_STATUS_CURR);
+    assert_null(parsed->next);
+    assert_string_equal(parsed->dsc, "desc");
+    assert_string_equal(parsed->ref, "ref");
+    assert_string_equal(parsed->when->cond, "when-cond");
+    assert_string_equal(*parsed->iffeatures, "iff");
+    assert_string_equal(parsed->child->name, "anyd");
+    assert_int_equal(parsed->child->nodetype, LYS_ANYDATA);
+    assert_string_equal(parsed->child->next->name, "anyx");
+    assert_int_equal(parsed->child->next->nodetype, LYS_ANYXML);
+    assert_string_equal(parsed->child->next->next->name, "subcont");
+    assert_int_equal(parsed->child->next->next->nodetype, LYS_CONTAINER);
+    assert_string_equal(parsed->child->next->next->next->name, "leaf");
+    assert_int_equal(parsed->child->next->next->next->nodetype, LYS_LEAF);
+    assert_string_equal(parsed->child->next->next->next->next->name, "llist");
+    assert_int_equal(parsed->child->next->next->next->next->nodetype, LYS_LEAFLIST);
+    assert_string_equal(parsed->child->next->next->next->next->next->name, "list");
+    assert_int_equal(parsed->child->next->next->next->next->next->nodetype, LYS_LIST);
+    assert_string_equal(parsed->child->next->next->next->next->next->next->name, "uses-name");
+    assert_int_equal(parsed->child->next->next->next->next->next->next->nodetype, LYS_USES);
+    assert_string_equal(parsed->child->next->next->next->next->next->next->next->name, "choice");
+    assert_int_equal(parsed->child->next->next->next->next->next->next->next->nodetype, LYS_CHOICE);
+    assert_null(parsed->child->next->next->next->next->next->next->next->next);
+    assert_string_equal(parsed->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(parsed->exts[0].insubstmt_index, 0);
+    assert_int_equal(parsed->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<case name=\"case-name\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_case *)siblings;
+    assert_string_equal(parsed->name, "case-name");
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_choice_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_node *siblings = NULL;
+    struct tree_node_meta node_meta = {NULL, &siblings};
+    struct lysp_node_choice *parsed = NULL;
+
+    /* max subelems */
+    st->yin_ctx->mod_version = LYS_VERSION_1_1;
+    data = ELEMENT_WRAPPER_START
+                "<choice name=\"choice-name\">"
+                    "<anydata name=\"anyd\"/>"
+                    "<anyxml name=\"anyx\"/>"
+                    "<case name=\"sub-case\"/>"
+                    "<choice name=\"choice\"/>"
+                    "<config value=\"true\"/>"
+                    "<container name=\"subcont\"/>"
+                    "<default value=\"def\"/>"
+                    "<description><text>desc</text></description>"
+                    "<if-feature name=\"iff\"/>"
+                    "<leaf name=\"leaf\"> <type name=\"type\"/> </leaf>"
+                    "<leaf-list name=\"llist\"> <type name=\"type\"/> </leaf-list>"
+                    "<list name=\"list\"/>"
+                    "<mandatory value=\"true\" />"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"current\"/>"
+                    "<when condition=\"when-cond\"/>"
+                    EXT_SUBELEM
+                "</choice>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_choice *)siblings;
+    assert_string_equal(parsed->name, "choice-name");
+    assert_null(parsed->parent);
+    assert_int_equal(parsed->nodetype, LYS_CHOICE);
+    assert_true(parsed->flags & LYS_CONFIG_W && parsed->flags & LYS_MAND_TRUE  && parsed->flags & LYS_STATUS_CURR);
+    assert_null(parsed->next);
+    assert_string_equal(parsed->dsc, "desc");
+    assert_string_equal(parsed->ref, "ref");
+    assert_string_equal(parsed->when->cond, "when-cond");
+    assert_string_equal(*parsed->iffeatures, "iff");
+    assert_string_equal(parsed->child->name, "anyd");
+    assert_int_equal(parsed->child->nodetype, LYS_ANYDATA);
+    assert_string_equal(parsed->child->next->name, "anyx");
+    assert_int_equal(parsed->child->next->nodetype, LYS_ANYXML);
+    assert_string_equal(parsed->child->next->next->name, "sub-case");
+    assert_int_equal(parsed->child->next->next->nodetype, LYS_CASE);
+    assert_string_equal(parsed->child->next->next->next->name, "choice");
+    assert_int_equal(parsed->child->next->next->next->nodetype, LYS_CHOICE);
+    assert_string_equal(parsed->child->next->next->next->next->name, "subcont");
+    assert_int_equal(parsed->child->next->next->next->next->nodetype, LYS_CONTAINER);
+    assert_string_equal(parsed->child->next->next->next->next->next->name, "leaf");
+    assert_int_equal(parsed->child->next->next->next->next->next->nodetype, LYS_LEAF);
+    assert_string_equal(parsed->child->next->next->next->next->next->next->name, "llist");
+    assert_int_equal(parsed->child->next->next->next->next->next->next->nodetype, LYS_LEAFLIST);
+    assert_string_equal(parsed->child->next->next->next->next->next->next->next->name, "list");
+    assert_int_equal(parsed->child->next->next->next->next->next->next->next->nodetype, LYS_LIST);
+    assert_null(parsed->child->next->next->next->next->next->next->next->next);
+    assert_string_equal(parsed->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(parsed->exts[0].insubstmt_index, 0);
+    assert_int_equal(parsed->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<choice name=\"choice-name\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &node_meta, NULL, NULL), LY_SUCCESS);
+    parsed = (struct lysp_node_choice *)siblings;
+    assert_string_equal(parsed->name, "choice-name");
+    lysp_node_free(st->ctx, siblings);
+    siblings = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_inout_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_action_inout inout = {};
+    struct inout_meta inout_meta = {NULL, &inout};
+
+    /* max subelements */
+    st->yin_ctx->mod_version = LYS_VERSION_1_1;
+    data = ELEMENT_WRAPPER_START
+                "<input>"
+                    "<anydata name=\"anyd\"/>"
+                    "<anyxml name=\"anyx\"/>"
+                    "<choice name=\"choice\"/>"
+                    "<container name=\"subcont\"/>"
+                    "<grouping name=\"sub-grp\"/>"
+                    "<leaf name=\"leaf\"> <type name=\"type\"/> </leaf>"
+                    "<leaf-list name=\"llist\"> <type name=\"type\"/> </leaf-list>"
+                    "<list name=\"list\"/>"
+                    "<must condition=\"cond\"/>"
+                    "<typedef name=\"tpdf\"> <type name=\"type\"/> </typedef>"
+                    "<uses name=\"uses-name\"/>"
+                    EXT_SUBELEM
+                "</input>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &inout_meta, NULL, NULL), LY_SUCCESS);
+    assert_null(inout.parent);
+    assert_int_equal(inout.nodetype, LYS_INPUT);
+    assert_string_equal(inout.musts->arg, "cond");
+    assert_string_equal(inout.typedefs->name, "tpdf");
+    assert_string_equal(inout.groupings->name, "sub-grp");
+    assert_string_equal(inout.data->name, "anyd");
+    assert_int_equal(inout.data->nodetype, LYS_ANYDATA);
+    assert_string_equal(inout.data->next->name, "anyx");
+    assert_int_equal(inout.data->next->nodetype, LYS_ANYXML);
+    assert_string_equal(inout.data->next->next->name, "choice");
+    assert_int_equal(inout.data->next->next->nodetype, LYS_CHOICE);
+    assert_string_equal(inout.data->next->next->next->name, "subcont");
+    assert_int_equal(inout.data->next->next->next->nodetype, LYS_CONTAINER);
+    assert_string_equal(inout.data->next->next->next->next->name, "leaf");
+    assert_int_equal(inout.data->next->next->next->next->nodetype, LYS_LEAF);
+    assert_string_equal(inout.data->next->next->next->next->next->name, "llist");
+    assert_int_equal(inout.data->next->next->next->next->next->nodetype, LYS_LEAFLIST);
+    assert_string_equal(inout.data->next->next->next->next->next->next->name, "list");
+    assert_int_equal(inout.data->next->next->next->next->next->next->nodetype, LYS_LIST);
+    assert_string_equal(inout.data->next->next->next->next->next->next->next->name, "uses-name");
+    assert_int_equal(inout.data->next->next->next->next->next->next->next->nodetype, LYS_USES);
+    assert_null(inout.data->next->next->next->next->next->next->next->next);
+    assert_string_equal(inout.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(inout.exts[0].insubstmt_index, 0);
+    assert_int_equal(inout.exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_action_inout_free(st->ctx, &inout);
+    memset(&inout, 0, sizeof inout);
+
+    /* max subelements */
+    st->yin_ctx->mod_version = LYS_VERSION_1_1;
+    data = ELEMENT_WRAPPER_START
+                "<output>"
+                    "<anydata name=\"anyd\"/>"
+                    "<anyxml name=\"anyx\"/>"
+                    "<choice name=\"choice\"/>"
+                    "<container name=\"subcont\"/>"
+                    "<grouping name=\"sub-grp\"/>"
+                    "<leaf name=\"leaf\"> <type name=\"type\"/> </leaf>"
+                    "<leaf-list name=\"llist\"> <type name=\"type\"/> </leaf-list>"
+                    "<list name=\"list\"/>"
+                    "<must condition=\"cond\"/>"
+                    "<typedef name=\"tpdf\"> <type name=\"type\"/> </typedef>"
+                    "<uses name=\"uses-name\"/>"
+                    EXT_SUBELEM
+                "</output>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &inout_meta, NULL, NULL), LY_SUCCESS);
+    assert_null(inout.parent);
+    assert_int_equal(inout.nodetype, LYS_OUTPUT);
+    assert_string_equal(inout.musts->arg, "cond");
+    assert_string_equal(inout.typedefs->name, "tpdf");
+    assert_string_equal(inout.groupings->name, "sub-grp");
+    assert_string_equal(inout.data->name, "anyd");
+    assert_int_equal(inout.data->nodetype, LYS_ANYDATA);
+    assert_string_equal(inout.data->next->name, "anyx");
+    assert_int_equal(inout.data->next->nodetype, LYS_ANYXML);
+    assert_string_equal(inout.data->next->next->name, "choice");
+    assert_int_equal(inout.data->next->next->nodetype, LYS_CHOICE);
+    assert_string_equal(inout.data->next->next->next->name, "subcont");
+    assert_int_equal(inout.data->next->next->next->nodetype, LYS_CONTAINER);
+    assert_string_equal(inout.data->next->next->next->next->name, "leaf");
+    assert_int_equal(inout.data->next->next->next->next->nodetype, LYS_LEAF);
+    assert_string_equal(inout.data->next->next->next->next->next->name, "llist");
+    assert_int_equal(inout.data->next->next->next->next->next->nodetype, LYS_LEAFLIST);
+    assert_string_equal(inout.data->next->next->next->next->next->next->name, "list");
+    assert_int_equal(inout.data->next->next->next->next->next->next->nodetype, LYS_LIST);
+    assert_string_equal(inout.data->next->next->next->next->next->next->next->name, "uses-name");
+    assert_int_equal(inout.data->next->next->next->next->next->next->next->nodetype, LYS_USES);
+    assert_null(inout.data->next->next->next->next->next->next->next->next);
+    assert_string_equal(inout.exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(inout.exts[0].insubstmt_index, 0);
+    assert_int_equal(inout.exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_action_inout_free(st->ctx, &inout);
+    memset(&inout, 0, sizeof inout);
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<input><leaf name=\"l\"><type name=\"empty\"/></leaf></input>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &inout_meta, NULL, NULL), LY_SUCCESS);
+    lysp_action_inout_free(st->ctx, &inout);
+    memset(&inout, 0, sizeof inout);
+
+    data = ELEMENT_WRAPPER_START "<output><leaf name=\"l\"><type name=\"empty\"/></leaf></output>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &inout_meta, NULL, NULL), LY_SUCCESS);
+    lysp_action_inout_free(st->ctx, &inout);
+    memset(&inout, 0, sizeof inout);
+
+    /* invalid combinations */
+    data = ELEMENT_WRAPPER_START "<input name=\"test\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &inout_meta, NULL, NULL), LY_EVALID);
+    logbuf_assert("Unexpected attribute \"name\" of \"input\" element. Line number 1.");
+    memset(&inout, 0, sizeof inout);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_action_elem(void **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};
+
+    /* max subelems */
+    st->yin_ctx->mod_version = LYS_VERSION_1_1;
+    data = ELEMENT_WRAPPER_START
+                "<action name=\"act\">"
+                    "<description><text>desc</text></description>"
+                    "<grouping name=\"grouping\"/>"
+                    "<if-feature name=\"iff\"/>"
+                    "<input><uses name=\"uses-name\"/></input>"
+                    "<output><must condition=\"cond\"/><leaf name=\"l\"><type name=\"type\"/></leaf></output>"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"deprecated\"/>"
+                    "<typedef name=\"tpdf\"> <type name=\"type\"/> </typedef>"
+                    EXT_SUBELEM
+                "</action>"
+           ELEMENT_WRAPPER_END;
+    /* there must be parent for action */
+    act_meta.parent = NULL + 1;
+    assert_int_equal(test_element_helper(st, data, &act_meta, NULL, NULL), LY_SUCCESS);
+    act_meta.parent = NULL;
+    assert_non_null(actions->parent);
+    assert_int_equal(actions->nodetype, LYS_ACTION);
+    assert_true(actions->flags & LYS_STATUS_DEPRC);
+    assert_string_equal(actions->name, "act");
+    assert_string_equal(actions->dsc, "desc");
+    assert_string_equal(actions->ref, "ref");
+    assert_string_equal(*actions->iffeatures, "iff");
+    assert_string_equal(actions->typedefs->name, "tpdf");
+    assert_string_equal(actions->groupings->name, "grouping");
+    assert_string_equal(actions->input.data->name, "uses-name");
+    assert_string_equal(actions->output.musts->arg, "cond");
+    assert_string_equal(actions->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(actions->exts[0].insubstmt_index, 0);
+    assert_int_equal(actions->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    FREE_ARRAY(st->ctx, actions, lysp_action_free)
+    actions = NULL;
+
+    st->yin_ctx->mod_version = LYS_VERSION_1_1;
+    data = ELEMENT_WRAPPER_START
+                "<rpc name=\"act\">"
+                    "<description><text>desc</text></description>"
+                    "<grouping name=\"grouping\"/>"
+                    "<if-feature name=\"iff\"/>"
+                    "<input><uses name=\"uses-name\"/></input>"
+                    "<output><must condition=\"cond\"/><leaf name=\"l\"><type name=\"type\"/></leaf></output>"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"deprecated\"/>"
+                    "<typedef name=\"tpdf\"> <type name=\"type\"/> </typedef>"
+                    EXT_SUBELEM
+                "</rpc>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &act_meta, NULL, NULL), LY_SUCCESS);
+    assert_null(actions->parent);
+    assert_int_equal(actions->nodetype, LYS_RPC);
+    assert_true(actions->flags & LYS_STATUS_DEPRC);
+    assert_string_equal(actions->name, "act");
+    assert_string_equal(actions->dsc, "desc");
+    assert_string_equal(actions->ref, "ref");
+    assert_string_equal(*actions->iffeatures, "iff");
+    assert_string_equal(actions->typedefs->name, "tpdf");
+    assert_string_equal(actions->groupings->name, "grouping");
+    assert_string_equal(actions->input.data->name, "uses-name");
+    assert_string_equal(actions->output.musts->arg, "cond");
+    assert_string_equal(actions->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(actions->exts[0].insubstmt_index, 0);
+    assert_int_equal(actions->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    FREE_ARRAY(st->ctx, actions, lysp_action_free)
+    actions = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START "<action name=\"act\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &act_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(actions->name, "act");
+    FREE_ARRAY(st->ctx, actions, lysp_action_free)
+    actions = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_augment_elem(void **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};
+
+    st->yin_ctx->mod_version = LYS_VERSION_1_1;
+    data = ELEMENT_WRAPPER_START
+                "<augment target-node=\"target\">"
+                    "<action name=\"action\"/>"
+                    "<anydata name=\"anyd\"/>"
+                    "<anyxml name=\"anyx\"/>"
+                    "<case name=\"case\"/>"
+                    "<choice name=\"choice\"/>"
+                    "<container name=\"subcont\"/>"
+                    "<description><text>desc</text></description>"
+                    "<if-feature name=\"iff\"/>"
+                    "<leaf name=\"leaf\"> <type name=\"type\"/> </leaf>"
+                    "<leaf-list name=\"llist\"> <type name=\"type\"/> </leaf-list>"
+                    "<list name=\"list\"/>"
+                    "<notification name=\"notif\"/>"
+                    "<reference><text>ref</text></reference>"
+                    "<status value=\"current\"/>"
+                    "<uses name=\"uses\"/>"
+                    "<when condition=\"when-cond\"/>"
+                    EXT_SUBELEM
+                "</augment>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &aug_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(augments->nodeid, "target");
+    assert_null(augments->parent);
+    assert_int_equal(augments->nodetype, LYS_AUGMENT);
+    assert_true(augments->flags & LYS_STATUS_CURR);
+    assert_string_equal(augments->dsc, "desc");
+    assert_string_equal(augments->ref, "ref");
+    assert_string_equal(augments->when->cond, "when-cond");
+    assert_string_equal(*augments->iffeatures, "iff");
+    assert_string_equal(augments->child->name, "anyd");
+    assert_int_equal(augments->child->nodetype, LYS_ANYDATA);
+    assert_string_equal(augments->child->next->name, "anyx");
+    assert_int_equal(augments->child->next->nodetype, LYS_ANYXML);
+    assert_string_equal(augments->child->next->next->name, "case");
+    assert_int_equal(augments->child->next->next->nodetype, LYS_CASE);
+    assert_string_equal(augments->child->next->next->next->name, "choice");
+    assert_int_equal(augments->child->next->next->next->nodetype, LYS_CHOICE);
+    assert_string_equal(augments->child->next->next->next->next->name, "subcont");
+    assert_int_equal(augments->child->next->next->next->next->nodetype, LYS_CONTAINER);
+    assert_string_equal(augments->child->next->next->next->next->next->name, "leaf");
+    assert_int_equal(augments->child->next->next->next->next->next->nodetype, LYS_LEAF);
+    assert_string_equal(augments->child->next->next->next->next->next->next->name, "llist");
+    assert_int_equal(augments->child->next->next->next->next->next->next->nodetype, LYS_LEAFLIST);
+    assert_string_equal(augments->child->next->next->next->next->next->next->next->name, "list");
+    assert_int_equal(augments->child->next->next->next->next->next->next->next->nodetype, LYS_LIST);
+    assert_string_equal(augments->child->next->next->next->next->next->next->next->next->name, "uses");
+    assert_int_equal(augments->child->next->next->next->next->next->next->next->next->nodetype, LYS_USES);
+    assert_null(augments->child->next->next->next->next->next->next->next->next->next);
+    assert_string_equal(augments->actions->name, "action");
+    assert_string_equal(augments->notifs->name, "notif");
+    assert_string_equal(augments->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(augments->exts[0].insubstmt_index, 0);
+    assert_int_equal(augments->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    FREE_ARRAY(st->ctx, augments, lysp_augment_free)
+    augments = NULL;
+
+    data = ELEMENT_WRAPPER_START "<augment target-node=\"target\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &aug_meta, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(augments->nodeid, "target");
+    FREE_ARRAY(st->ctx, augments, lysp_augment_free)
+    augments = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_deviate_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_deviate *deviates = NULL;
+    struct lysp_deviate_add *d_add;
+    struct lysp_deviate_rpl *d_rpl;
+    struct lysp_deviate_del *d_del;
+
+    /* all valid arguments with min subelems */
+    data = ELEMENT_WRAPPER_START "<deviate value=\"not-supported\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(deviates->mod, LYS_DEV_NOT_SUPPORTED);
+    lysp_deviate_free(st->ctx, deviates);
+    free(deviates);
+    deviates = NULL;
+
+    data = ELEMENT_WRAPPER_START "<deviate value=\"add\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(deviates->mod, LYS_DEV_ADD);
+    lysp_deviate_free(st->ctx, deviates);
+    free(deviates);
+    deviates = NULL;
+
+    data = ELEMENT_WRAPPER_START "<deviate value=\"replace\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(deviates->mod, LYS_DEV_REPLACE);
+    lysp_deviate_free(st->ctx, deviates);
+    free(deviates);
+    deviates = NULL;
+
+    data = ELEMENT_WRAPPER_START "<deviate value=\"delete\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(deviates->mod, LYS_DEV_DELETE);
+    lysp_deviate_free(st->ctx, deviates);
+    free(deviates);
+    deviates = NULL;
+
+    /* max subelems and valid arguments */
+    data = ELEMENT_WRAPPER_START
+                "<deviate value=\"not-supported\">"
+                    EXT_SUBELEM
+                "</deviate>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_SUCCESS);
+    assert_int_equal(deviates->mod, LYS_DEV_NOT_SUPPORTED);
+    assert_string_equal(deviates->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(deviates->exts[0].insubstmt_index, 0);
+    assert_int_equal(deviates->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_deviate_free(st->ctx, deviates);
+    free(deviates);
+    deviates = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<deviate value=\"add\">"
+                    "<units name=\"units\"/>"
+                    "<must condition=\"cond\"/>"
+                    "<unique tag=\"utag\"/>"
+                    "<default value=\"def\"/>"
+                    "<config value=\"true\"/>"
+                    "<mandatory value=\"true\"/>"
+                    "<min-elements value=\"5\"/>"
+                    "<max-elements value=\"15\"/>"
+                    EXT_SUBELEM
+                "</deviate>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_SUCCESS);
+    d_add = (struct lysp_deviate_add *)deviates;
+    assert_int_equal(d_add->mod, LYS_DEV_ADD);
+    assert_null(d_add->next);
+    assert_string_equal(d_add->units, "units");
+    assert_string_equal(d_add->musts->arg, "cond");
+    assert_string_equal(*d_add->uniques, "utag");
+    assert_string_equal(*d_add->dflts, "def");
+    assert_true(d_add->flags & LYS_MAND_TRUE && d_add->flags & LYS_CONFIG_W);
+    assert_int_equal(d_add->min, 5);
+    assert_int_equal(d_add->max, 15);
+    assert_string_equal(deviates->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(deviates->exts[0].insubstmt_index, 0);
+    assert_int_equal(deviates->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_deviate_free(st->ctx, deviates);
+    free(deviates);
+    deviates = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<deviate value=\"replace\">"
+                    "<type name=\"newtype\"/>"
+                    "<units name=\"uni\"/>"
+                    "<default value=\"def\"/>"
+                    "<config value=\"true\"/>"
+                    "<mandatory value=\"true\"/>"
+                    "<min-elements value=\"5\"/>"
+                    "<max-elements value=\"15\"/>"
+                    EXT_SUBELEM
+                "</deviate>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_SUCCESS);
+    d_rpl = (struct lysp_deviate_rpl *)deviates;
+    assert_int_equal(d_rpl->mod, LYS_DEV_REPLACE);
+    assert_null(d_rpl->next);
+    assert_string_equal(d_rpl->type->name, "newtype");
+    assert_string_equal(d_rpl->units, "uni");
+    assert_string_equal(d_rpl->dflt, "def");
+    assert_true(d_rpl->flags & LYS_MAND_TRUE && d_rpl->flags & LYS_CONFIG_W);
+    assert_int_equal(d_rpl->min, 5);
+    assert_int_equal(d_rpl->max, 15);
+    assert_string_equal(deviates->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(deviates->exts[0].insubstmt_index, 0);
+    assert_int_equal(deviates->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_deviate_free(st->ctx, deviates);
+    free(deviates);
+    deviates = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<deviate value=\"delete\">"
+                    "<units name=\"u\"/>"
+                    "<must condition=\"c\"/>"
+                    "<unique tag=\"tag\"/>"
+                    "<default value=\"default\"/>"
+                    EXT_SUBELEM
+                "</deviate>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_SUCCESS);
+    d_del = (struct lysp_deviate_del *)deviates;
+    assert_int_equal(d_del->mod, LYS_DEV_DELETE);
+    assert_null(d_del->next);
+    assert_string_equal(d_del->units, "u");
+    assert_string_equal(d_del->musts->arg, "c");
+    assert_string_equal(*d_del->uniques, "tag");
+    assert_string_equal(*d_del->dflts, "default");
+    assert_string_equal(deviates->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(deviates->exts[0].insubstmt_index, 0);
+    assert_int_equal(deviates->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_deviate_free(st->ctx, deviates);
+    free(deviates);
+    deviates = NULL;
+
+    /* invalid arguments */
+    data = ELEMENT_WRAPPER_START "<deviate value=\"\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"\" of \"value\" attribute in \"deviate\" element. Valid values are \"not-supported\", \"add\", \"replace\" and \"delete\". Line number 1.");
+    deviates = NULL;
+
+    data = ELEMENT_WRAPPER_START "<deviate value=\"invalid\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"invalid\" of \"value\" attribute in \"deviate\" element. Valid values are \"not-supported\", \"add\", \"replace\" and \"delete\". Line number 1.");
+    deviates = NULL;
+
+    data = ELEMENT_WRAPPER_START "<deviate value=\"ad\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"ad\" of \"value\" attribute in \"deviate\" element. Valid values are \"not-supported\", \"add\", \"replace\" and \"delete\". Line number 1.");
+    deviates = NULL;
+
+    data = ELEMENT_WRAPPER_START "<deviate value=\"adds\" />" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_EVALID);
+    logbuf_assert("Invalid value \"adds\" of \"value\" attribute in \"deviate\" element. Valid values are \"not-supported\", \"add\", \"replace\" and \"delete\". Line number 1.");
+    deviates = NULL;
+
+    data = ELEMENT_WRAPPER_START
+                "<deviate value=\"not-supported\">"
+                    "<must condition=\"c\"/>"
+                "</deviate>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviates, NULL, NULL), LY_EVALID);
+    logbuf_assert("Deviate of this type doesn't allow \"must\" as it's sub-element. Line number 1.");
+
+    st->finished_correctly = true;
+}
+
+static void
+test_deviation_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_deviation *deviations = NULL;
+
+    /* min subelems */
+    data = ELEMENT_WRAPPER_START
+                "<deviation target-node=\"target\">"
+                    "<deviate value=\"not-supported\"/>"
+                "</deviation>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviations, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(deviations->nodeid, "target");
+    assert_int_equal(deviations->deviates->mod, LYS_DEV_NOT_SUPPORTED);
+    FREE_ARRAY(st->ctx, deviations, lysp_deviation_free);
+    deviations = NULL;
+
+    /* max subelems */
+    data = ELEMENT_WRAPPER_START
+                "<deviation target-node=\"target\">"
+                    "<reference><text>ref</text></reference>"
+                    "<description><text>desc</text></description>"
+                    "<deviate value=\"add\"/>"
+                    EXT_SUBELEM
+                "</deviation>"
+           ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviations, NULL, NULL), LY_SUCCESS);
+    assert_string_equal(deviations->nodeid, "target");
+    assert_int_equal(deviations->deviates->mod, LYS_DEV_ADD);
+    assert_string_equal(deviations->ref, "ref");
+    assert_string_equal(deviations->dsc, "desc");
+    assert_string_equal(deviations->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(deviations->exts[0].insubstmt_index, 0);
+    assert_int_equal(deviations->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    FREE_ARRAY(st->ctx, deviations, lysp_deviation_free);
+    deviations = NULL;
+
+    /* invalid */
+    data = ELEMENT_WRAPPER_START "<deviation target-node=\"target\"/>" ELEMENT_WRAPPER_END;
+    assert_int_equal(test_element_helper(st, data, &deviations, NULL, NULL), LY_EVALID);
+    FREE_ARRAY(st->ctx, deviations, lysp_deviation_free);
+    deviations = NULL;
+    logbuf_assert("Missing mandatory sub-element \"deviate\" of \"deviation\" element. Line number 1.");
+    /* TODO */
+    st->finished_correctly = true;
+}
+
+static void
+test_module_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lys_module *lys_mod = NULL;
+    struct lysp_module *lysp_mod = NULL;
+
+    /* max subelems */
+    lys_mod = calloc(1, sizeof *lys_mod);
+    lysp_mod = calloc(1, sizeof *lysp_mod);
+    lys_mod->ctx = st->ctx;
+    lysp_mod->mod = lys_mod;
+    data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" name=\"mod\">\n"
+                "<yang-version value=\"1.1\"/>\n"
+                "<namespace uri=\"ns\"/>\n"
+                "<prefix value=\"pref\"/>\n"
+                "<include module=\"b-mod\"/>\n"
+                "<import module=\"a-mod\"><prefix value=\"imp-pref\"/></import>\n"
+                "<organization><text>org</text></organization>\n"
+                "<contact><text>contact</text></contact>\n"
+                "<description><text>desc</text></description>"
+                "<reference><text>ref</text></reference>\n"
+                "<revision date=\"2019-02-02\"/>\n"
+                "<anydata name=\"anyd\"/>\n"
+                "<anyxml name=\"anyx\"/>\n"
+                "<choice name=\"choice\"/>\n"
+                "<container name=\"cont\"/>\n"
+                "<leaf name=\"leaf\"> <type name=\"type\"/> </leaf>\n"
+                "<leaf-list name=\"llist\"> <type name=\"type\"/> </leaf-list>\n"
+                "<list name=\"sub-list\"/>\n"
+                "<uses name=\"uses-name\"/>\n"
+                "<augment target-node=\"target\"/>\n"
+                "<deviation target-node=\"target\">""<deviate value=\"not-supported\"/>""</deviation>\n"
+                "<extension name=\"ext\"/>\n"
+                "<feature name=\"feature\"/>\n"
+                "<grouping name=\"grp\"/>\n"
+                "<identity name=\"ident-name\"/>\n"
+                "<notification name=\"notf\"/>\n"
+                "<rpc name=\"rpc-name\"/>\n"
+                "<typedef name=\"tpdf\"> <type name=\"type\"/> </typedef>\n"
+                EXT_SUBELEM"\n"
+           "</module>\n";
+    assert_int_equal(lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx), LY_SUCCESS);
+
+    assert_int_equal(yin_parse_mod(st->yin_ctx, lysp_mod), LY_SUCCESS);
+    assert_string_equal(lysp_mod->mod->name, "mod");
+    assert_string_equal(lysp_mod->revs, "2019-02-02");
+    assert_string_equal(lysp_mod->mod->ns, "ns");
+    assert_string_equal(lysp_mod->mod->prefix, "pref");
+    assert_null(lysp_mod->mod->filepath);
+    assert_string_equal(lysp_mod->mod->org, "org");
+    assert_string_equal(lysp_mod->mod->contact, "contact");
+    assert_string_equal(lysp_mod->mod->dsc, "desc");
+    assert_string_equal(lysp_mod->mod->ref, "ref");
+    assert_int_equal(lysp_mod->mod->version, LYS_VERSION_1_1);
+    assert_string_equal(lysp_mod->imports->name, "a-mod");
+    assert_string_equal(lysp_mod->includes->name, "b-mod");
+    assert_string_equal(lysp_mod->extensions->name, "ext");
+    assert_string_equal(lysp_mod->features->name, "feature");
+    assert_string_equal(lysp_mod->identities->name, "ident-name");
+    assert_string_equal(lysp_mod->typedefs->name, "tpdf");
+    assert_string_equal(lysp_mod->groupings->name, "grp");
+    assert_string_equal(lysp_mod->data->name, "anyd");
+    assert_int_equal(lysp_mod->data->nodetype, LYS_ANYDATA);
+    assert_string_equal(lysp_mod->data->next->name, "anyx");
+    assert_int_equal(lysp_mod->data->next->nodetype, LYS_ANYXML);
+    assert_string_equal(lysp_mod->data->next->next->name, "choice");
+    assert_int_equal(lysp_mod->data->next->next->nodetype, LYS_CHOICE);
+    assert_string_equal(lysp_mod->data->next->next->next->name, "cont");
+    assert_int_equal(lysp_mod->data->next->next->next->nodetype, LYS_CONTAINER);
+    assert_string_equal(lysp_mod->data->next->next->next->next->name, "leaf");
+    assert_int_equal(lysp_mod->data->next->next->next->next->nodetype, LYS_LEAF);
+    assert_string_equal(lysp_mod->data->next->next->next->next->next->name, "llist");
+    assert_int_equal(lysp_mod->data->next->next->next->next->next->nodetype, LYS_LEAFLIST);
+    assert_string_equal(lysp_mod->data->next->next->next->next->next->next->name, "sub-list");
+    assert_int_equal(lysp_mod->data->next->next->next->next->next->next->nodetype, LYS_LIST);
+    assert_string_equal(lysp_mod->data->next->next->next->next->next->next->next->name, "uses-name");
+    assert_int_equal(lysp_mod->data->next->next->next->next->next->next->next->nodetype, LYS_USES);
+    assert_null(lysp_mod->data->next->next->next->next->next->next->next->next);
+    assert_string_equal(lysp_mod->augments->nodeid, "target");
+    assert_string_equal(lysp_mod->rpcs->name, "rpc-name");
+    assert_string_equal(lysp_mod->notifs->name, "notf");
+    assert_string_equal(lysp_mod->deviations->nodeid, "target");
+    assert_string_equal(lysp_mod->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(lysp_mod->exts[0].insubstmt_index, 0);
+    assert_int_equal(lysp_mod->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+    lysp_module_free(lysp_mod);
+    lys_module_free(lys_mod, NULL);
+
+    /* min subelems */
+    lyxml_ctx_free(st->yin_ctx->xmlctx);
+    lys_mod = calloc(1, sizeof *lys_mod);
+    lysp_mod = calloc(1, sizeof *lysp_mod);
+    lys_mod->ctx = st->ctx;
+    lysp_mod->mod = lys_mod;
+    data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" name=\"mod\">"
+                "<namespace uri=\"ns\"/>"
+                "<prefix value=\"pref\"/>"
+                "<yang-version value=\"1.1\"/>"
+           "</module>";
+    assert_int_equal(lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx), LY_SUCCESS);
+    assert_int_equal(yin_parse_mod(st->yin_ctx, lysp_mod), LY_SUCCESS);
+    assert_string_equal(lysp_mod->mod->name, "mod");
+    lysp_module_free(lysp_mod);
+    lys_module_free(lys_mod, NULL);
+
+    /* incorrect subelem order */
+    lyxml_ctx_free(st->yin_ctx->xmlctx);
+    lys_mod = calloc(1, sizeof *lys_mod);
+    lysp_mod = calloc(1, sizeof *lysp_mod);
+    lys_mod->ctx = st->ctx;
+    lysp_mod->mod = lys_mod;
+    data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" name=\"mod\">"
+                "<feature name=\"feature\"/>\n"
+                "<namespace uri=\"ns\"/>"
+                "<prefix value=\"pref\"/>"
+                "<yang-version value=\"1.1\"/>"
+           "</module>";
+    assert_int_equal(lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx), LY_SUCCESS);
+    assert_int_equal(yin_parse_mod(st->yin_ctx, lysp_mod), LY_EVALID);
+    logbuf_assert("Invalid order of module\'s sub-elements \"namespace\" can\'t appear after \"feature\". Line number 2.");
+    lysp_module_free(lysp_mod);
+    lys_module_free(lys_mod, NULL);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_submodule_elem(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lysp_submodule *lysp_submod = NULL;
+
+    /* max subelements */
+    lysp_submod = calloc(1, sizeof *lysp_submod);
+    data = "<submodule xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" name=\"mod\">\n"
+                "<yang-version value=\"1.1\"/>\n"
+                "<belongs-to module=\"mod-name\"><prefix value=\"pref\"/></belongs-to>"
+                "<include module=\"b-mod\"/>\n"
+                "<import module=\"a-mod\"><prefix value=\"imp-pref\"/></import>\n"
+                "<organization><text>org</text></organization>\n"
+                "<contact><text>contact</text></contact>\n"
+                "<description><text>desc</text></description>"
+                "<reference><text>ref</text></reference>\n"
+                "<revision date=\"2019-02-02\"/>\n"
+                "<anydata name=\"anyd\"/>\n"
+                "<anyxml name=\"anyx\"/>\n"
+                "<choice name=\"choice\"/>\n"
+                "<container name=\"cont\"/>\n"
+                "<leaf name=\"leaf\"> <type name=\"type\"/> </leaf>\n"
+                "<leaf-list name=\"llist\"> <type name=\"type\"/> </leaf-list>\n"
+                "<list name=\"sub-list\"/>\n"
+                "<uses name=\"uses-name\"/>\n"
+                "<augment target-node=\"target\"/>\n"
+                "<deviation target-node=\"target\">""<deviate value=\"not-supported\"/>""</deviation>\n"
+                "<extension name=\"ext\"/>\n"
+                "<feature name=\"feature\"/>\n"
+                "<grouping name=\"grp\"/>\n"
+                "<identity name=\"ident-name\"/>\n"
+                "<notification name=\"notf\"/>\n"
+                "<rpc name=\"rpc-name\"/>\n"
+                "<typedef name=\"tpdf\"> <type name=\"type\"/> </typedef>\n"
+                EXT_SUBELEM"\n"
+           "</submodule>\n";
+    assert_int_equal(lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx), LY_SUCCESS);
+    assert_int_equal(yin_parse_submod(st->yin_ctx, lysp_submod), LY_SUCCESS);
+
+    assert_string_equal(lysp_submod->name, "mod");
+    assert_string_equal(lysp_submod->revs, "2019-02-02");
+    assert_string_equal(lysp_submod->prefix, "pref");
+    assert_null(lysp_submod->filepath);
+    assert_string_equal(lysp_submod->org, "org");
+    assert_string_equal(lysp_submod->contact, "contact");
+    assert_string_equal(lysp_submod->dsc, "desc");
+    assert_string_equal(lysp_submod->ref, "ref");
+    assert_int_equal(lysp_submod->version, LYS_VERSION_1_1);
+    assert_string_equal(lysp_submod->imports->name, "a-mod");
+    assert_string_equal(lysp_submod->includes->name, "b-mod");
+    assert_string_equal(lysp_submod->extensions->name, "ext");
+    assert_string_equal(lysp_submod->features->name, "feature");
+    assert_string_equal(lysp_submod->identities->name, "ident-name");
+    assert_string_equal(lysp_submod->typedefs->name, "tpdf");
+    assert_string_equal(lysp_submod->groupings->name, "grp");
+    assert_string_equal(lysp_submod->data->name, "anyd");
+    assert_int_equal(lysp_submod->data->nodetype, LYS_ANYDATA);
+    assert_string_equal(lysp_submod->data->next->name, "anyx");
+    assert_int_equal(lysp_submod->data->next->nodetype, LYS_ANYXML);
+    assert_string_equal(lysp_submod->data->next->next->name, "choice");
+    assert_int_equal(lysp_submod->data->next->next->nodetype, LYS_CHOICE);
+    assert_string_equal(lysp_submod->data->next->next->next->name, "cont");
+    assert_int_equal(lysp_submod->data->next->next->next->nodetype, LYS_CONTAINER);
+    assert_string_equal(lysp_submod->data->next->next->next->next->name, "leaf");
+    assert_int_equal(lysp_submod->data->next->next->next->next->nodetype, LYS_LEAF);
+    assert_string_equal(lysp_submod->data->next->next->next->next->next->name, "llist");
+    assert_int_equal(lysp_submod->data->next->next->next->next->next->nodetype, LYS_LEAFLIST);
+    assert_string_equal(lysp_submod->data->next->next->next->next->next->next->name, "sub-list");
+    assert_int_equal(lysp_submod->data->next->next->next->next->next->next->nodetype, LYS_LIST);
+    assert_string_equal(lysp_submod->data->next->next->next->next->next->next->next->name, "uses-name");
+    assert_int_equal(lysp_submod->data->next->next->next->next->next->next->next->nodetype, LYS_USES);
+    assert_null(lysp_submod->data->next->next->next->next->next->next->next->next);
+    assert_string_equal(lysp_submod->augments->nodeid, "target");
+    assert_string_equal(lysp_submod->rpcs->name, "rpc-name");
+    assert_string_equal(lysp_submod->notifs->name, "notf");
+    assert_string_equal(lysp_submod->deviations->nodeid, "target");
+    assert_string_equal(lysp_submod->exts[0].name, "urn:example:extensions:c-define");
+    assert_int_equal(lysp_submod->exts[0].insubstmt_index, 0);
+    assert_int_equal(lysp_submod->exts[0].insubstmt, LYEXT_SUBSTMT_SELF);
+
+    lysp_submodule_free(st->ctx, lysp_submod);
+
+    /* min subelemnts */
+    lyxml_ctx_free(st->yin_ctx->xmlctx);
+    lysp_submod = calloc(1, sizeof *lysp_submod);
+    data = "<submodule xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" name=\"submod\">"
+                "<yang-version value=\"1.0\"/>"
+                "<belongs-to module=\"mod-name\"><prefix value=\"pref\"/></belongs-to>"
+           "</submodule>";
+    assert_int_equal(lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx), LY_SUCCESS);
+    assert_int_equal(yin_parse_submod(st->yin_ctx, lysp_submod), LY_SUCCESS);
+    assert_string_equal(lysp_submod->prefix, "pref");
+    assert_string_equal(lysp_submod->belongsto, "mod-name");
+    assert_int_equal(lysp_submod->version, LYS_VERSION_1_0);
+    lysp_submodule_free(st->ctx, lysp_submod);
+
+    /* incorrect subelem order */
+    lyxml_ctx_free(st->yin_ctx->xmlctx);
+    lysp_submod = calloc(1, sizeof *lysp_submod);
+    data = "<submodule xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" name=\"submod\">"
+                "<yang-version value=\"1.0\"/>"
+                "<reference><text>ref</text></reference>\n"
+                "<belongs-to module=\"mod-name\"><prefix value=\"pref\"/></belongs-to>"
+           "</submodule>";
+    assert_int_equal(lyxml_ctx_new(st->ctx, data, &st->yin_ctx->xmlctx), LY_SUCCESS);
+    assert_int_equal(yin_parse_submod(st->yin_ctx, lysp_submod), LY_EVALID);
+    logbuf_assert("Invalid order of submodule's sub-elements \"belongs-to\" can't appear after \"reference\". Line number 2.");
+    lysp_submodule_free(st->ctx, lysp_submod);
+
+    st->finished_correctly = true;
+}
+
+static void
+test_yin_parse_module(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lys_module *mod;
+    struct lys_yin_parser_ctx *yin_ctx = NULL;
+
+    mod = calloc(1, sizeof *mod);
+    mod->ctx = st->ctx;
+    data = "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" xmlns:md=\"urn:ietf:params:xml:ns:yang:ietf-yang-metadata\" name=\"a\"> \n"
+           "<yang-version value=\"1.1\"/>\n"
+           "<namespace uri=\"urn:tests:extensions:metadata:a\"/>\n"
+           "<prefix value=\"a\"/>\n"
+           "<import module=\"ietf-yang-metadata\">\n"
+                "<prefix value=\"md\"/>\n"
+           "</import>\n"
+           "<feature name=\"f\"/>\n"
+           "<md:annotation name=\"x\">\n"
+                "<description>\n"
+                "<text>test</text>\n"
+                "</description>\n"
+                "<reference>\n"
+                "<text>test</text>\n"
+                "</reference>\n"
+                "<if-feature name=\"f\"/>\n"
+                "<status value=\"current\"/>\n"
+                "<type name=\"uint8\"/>\n"
+                "<units name=\"meters\"/>\n"
+           "</md:annotation>\n"
+           "</module>\n";
+    assert_int_equal(yin_parse_module(&yin_ctx, data, mod), LY_SUCCESS);
+    assert_null(mod->parsed->exts->child->next->child);
+    assert_string_equal(mod->parsed->exts->child->next->arg, "test");
+    lys_module_free(mod, NULL);
+    yin_parser_ctx_free(yin_ctx);
+    mod = NULL;
+    yin_ctx = NULL;
+
+    mod = calloc(1, sizeof *mod);
+    mod->ctx = st->ctx;
+    data =  "<module name=\"example-foo\""
+             "xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\""
+             "xmlns:foo=\"urn:example:foo\""
+             "xmlns:myext=\"urn:example:extensions\">\n"
+
+                "<yang-version value=\"1.0\"/>\n"
+
+                "<namespace uri=\"urn:example:foo\"/>\n"
+                "<prefix value=\"foo\"/>\n"
+
+                "<import module=\"example-extensions\">\n"
+                    "<prefix value=\"myext\"/>\n"
+                "</import>\n"
+
+                "<list name=\"interface\">\n"
+                    "<key value=\"name\"/>\n"
+                    "<leaf name=\"name\">\n"
+                        "<type name=\"string\"/>\n"
+                    "</leaf>\n"
+                    "<leaf name=\"mtu\">\n"
+                        "<type name=\"uint32\"/>\n"
+                        "<description>\n"
+                            "<text>The MTU of the interface.</text>\n"
+                        "</description>\n"
+                        "<myext:c-define name=\"MY_MTU\"/>\n"
+                    "</leaf>\n"
+                "</list>\n"
+            "</module>\n";
+    assert_int_equal(yin_parse_module(&yin_ctx, data, mod), LY_SUCCESS);
+    lys_module_free(mod, NULL);
+    yin_parser_ctx_free(yin_ctx);
+    mod = NULL;
+    yin_ctx = NULL;
+
+    mod = calloc(1, sizeof *mod);
+    mod->ctx = st->ctx;
+    data =  "<module name=\"example-foo\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">\n"
+                "<yang-version value=\"1.0\"/>\n"
+                "<namespace uri=\"urn:example:foo\"/>\n"
+                "<prefix value=\"foo\"/>\n"
+            "</module>\n";
+    assert_int_equal(yin_parse_module(&yin_ctx, data, mod), LY_SUCCESS);
+    lys_module_free(mod, NULL);
+    yin_parser_ctx_free(yin_ctx);
+    mod = NULL;
+    yin_ctx = NULL;
+
+
+    mod = calloc(1, sizeof *mod);
+    mod->ctx = st->ctx;
+    data =  "<submodule name=\"example-foo\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
+            "</submodule>\n";
+    assert_int_equal(yin_parse_module(&yin_ctx, data, mod), LY_EINVAL);
+    logbuf_assert("Input data contains submodule which cannot be parsed directly without its main module.");
+    lys_module_free(mod, NULL);
+    yin_parser_ctx_free(yin_ctx);
+
+    mod = calloc(1, sizeof *mod);
+    mod->ctx = st->ctx;
+    data =  "<module name=\"example-foo\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">\n"
+                "<yang-version value=\"1.0\"/>\n"
+                "<namespace uri=\"urn:example:foo\"/>\n"
+                "<prefix value=\"foo\"/>\n"
+            "</module>"
+            "<module>";
+    assert_int_equal(yin_parse_module(&yin_ctx, data, mod), LY_EVALID);
+    logbuf_assert("Trailing garbage \"<module>\" after module, expected end-of-input. Line number 5.");
+    lys_module_free(mod, NULL);
+    yin_parser_ctx_free(yin_ctx);
+    mod = NULL;
+    yin_ctx = NULL;
+
+    st->finished_correctly = true;
+}
+
+static void
+test_yin_parse_submodule(void **state)
+{
+    struct test_parser_yin_state *st = *state;
+    const char *data;
+    struct lys_yin_parser_ctx *yin_ctx = NULL;
+    struct lysp_submodule *submod = NULL;
+    struct lys_parser_ctx main_ctx = {};
+
+    data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            "<submodule name=\"asub\""
+              "xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\""
+              "xmlns:a=\"urn:a\">"
+                "<yang-version value=\"1.0\"/>\n"
+                "<belongs-to module=\"a\">"
+                    "<prefix value=\"a_pref\"/>"
+                "</belongs-to>"
+                "<include module=\"atop\"/>"
+                "<feature name=\"fox\"/>"
+                "<notification name=\"bar-notif\">"
+                    "<if-feature name=\"bar\"/>"
+                "</notification>"
+                "<notification name=\"fox-notif\">"
+                    "<if-feature name=\"fox\"/>"
+                "</notification>"
+                "<augment target-node=\"/a_pref:top\">"
+                    "<if-feature name=\"bar\"/>"
+                    "<container name=\"bar-sub\"/>"
+                "</augment>"
+                "<augment target-node=\"/top\">"
+                    "<container name=\"bar-sub2\"/>"
+                "</augment>"
+            "</submodule>";
+    assert_int_equal(yin_parse_submodule(&yin_ctx, st->ctx, &main_ctx, data, &submod), LY_SUCCESS);
+    lysp_submodule_free(st->ctx, submod);
+    yin_parser_ctx_free(yin_ctx);
+    yin_ctx = NULL;
+    submod = NULL;
+
+    data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            "<submodule name=\"asub\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
+                "<yang-version value=\"1.0\"/>\n"
+                "<belongs-to module=\"a\">"
+                    "<prefix value=\"a_pref\"/>"
+                "</belongs-to>"
+            "</submodule>";
+    assert_int_equal(yin_parse_submodule(&yin_ctx, st->ctx, &main_ctx, data, &submod), LY_SUCCESS);
+    lysp_submodule_free(st->ctx, submod);
+    yin_parser_ctx_free(yin_ctx);
+    yin_ctx = NULL;
+    submod = NULL;
+
+    data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            "<module name=\"inval\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
+            "</module>";
+    assert_int_equal(yin_parse_submodule(&yin_ctx, st->ctx, &main_ctx, data, &submod), LY_EINVAL);
+    logbuf_assert("Input data contains module in situation when a submodule is expected.");
+    lysp_submodule_free(st->ctx, submod);
+    yin_parser_ctx_free(yin_ctx);
+    yin_ctx = NULL;
+    submod = NULL;
+
+    data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+            "<submodule name=\"asub\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
+                "<yang-version value=\"1.0\"/>\n"
+                "<belongs-to module=\"a\">"
+                    "<prefix value=\"a_pref\"/>"
+                "</belongs-to>"
+            "</submodule>"
+            "<submodule name=\"asub\" xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">"
+                "<yang-version value=\"1.0\"/>\n"
+                "<belongs-to module=\"a\">"
+                    "<prefix value=\"a_pref\"/>"
+                "</belongs-to>"
+            "</submodule>";
+    assert_int_equal(yin_parse_submodule(&yin_ctx, st->ctx, &main_ctx, data, &submod), LY_EVALID);
+    logbuf_assert("Trailing garbage \"<submodule name...\" after submodule, expected end-of-input. Line number 2.");
+    lysp_submodule_free(st->ctx, submod);
+    yin_parser_ctx_free(yin_ctx);
+    yin_ctx = NULL;
+    submod = NULL;
+
+    st->finished_correctly = true;
+}
+
+int
+main(void)
+{
+
+    const struct CMUnitTest tests[] = {
+        cmocka_unit_test_setup_teardown(test_yin_match_keyword, setup_f, teardown_f),
+        cmocka_unit_test_setup_teardown(test_yin_parse_element_generic, setup_f, teardown_f),
+        cmocka_unit_test_setup_teardown(test_yin_parse_extension_instance, setup_f, teardown_f),
+        cmocka_unit_test_setup_teardown(test_yin_parse_content, setup_f, teardown_f),
+        cmocka_unit_test_setup_teardown(test_validate_value, setup_f, teardown_f),
+
+        cmocka_unit_test(test_yin_match_argument_name),
+        cmocka_unit_test_setup_teardown(test_enum_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_bit_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_meta_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_import_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_status_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_ext_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_yin_element_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_yangversion_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_mandatory_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_argument_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_base_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_belongsto_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_config_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_default_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_err_app_tag_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_err_msg_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_fracdigits_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_iffeature_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_length_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_modifier_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_namespace_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_path_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_pattern_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_value_position_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_prefix_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_range_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_reqinstance_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_revision_date_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_unique_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_units_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_when_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_yin_text_value_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_type_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_max_elems_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_min_elems_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_ordby_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_any_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_leaf_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_leaf_list_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_presence_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_key_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_typedef_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_refine_elem, setup_element_test, teardown_element_test),
+        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_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),
+        cmocka_unit_test_setup_teardown(test_container_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_case_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_choice_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_inout_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_action_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_augment_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_deviate_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_deviation_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_module_elem, setup_element_test, teardown_element_test),
+        cmocka_unit_test_setup_teardown(test_submodule_elem, setup_element_test, teardown_element_test),
+
+        cmocka_unit_test_setup_teardown(test_yin_parse_module, setup_logger, teardown_logger),
+        cmocka_unit_test_setup_teardown(test_yin_parse_submodule, setup_logger, teardown_logger),
+    };
+
+    return cmocka_run_group_tests(tests, setup_ly_ctx, destroy_ly_ctx);
+}
diff --git a/tests/utests/schema/test_printer_yang.c b/tests/utests/schema/test_printer_yang.c
new file mode 100644
index 0000000..1f3f749
--- /dev/null
+++ b/tests/utests/schema/test_printer_yang.c
@@ -0,0 +1,232 @@
+/*
+ * @file test_printer_yang.c
+ * @author: Radek Krejci <rkrejci@cesnet.cz>
+ * @brief unit tests for functions from printer_yang.c
+ *
+ * Copyright (c) 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 <setjmp.h>
+#include <cmocka.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../../src/context.h"
+#include "../../src/printer_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 */
+#if ENABLE_LOGGER_CHECKING
+    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
+
+
+static void
+test_module(void **state)
+{
+    *state = test_module;
+
+    struct ly_ctx *ctx = {0};
+    const struct lys_module *mod;
+    const char *orig = "module a {\n"
+            "  yang-version 1.1;\n"
+            "  namespace \"urn:test:a\";\n"
+            "  prefix a;\n\n"
+            "  import ietf-yang-types {\n"
+            "    prefix yt;\n"
+            "    revision-date 2013-07-15;\n"
+            "    description\n"
+            "      \"YANG types\";\n"
+            "    reference\n"
+            "      \"RFC reference\";\n"
+            "  }\n\n"
+            "  organization\n"
+            "    \"ORG\";\n"
+            "  contact\n"
+            "    \"Radek Krejci.\";\n"
+            "  description\n"
+            "    \"Long multiline\n"
+            "      description.\";\n"
+            "  reference\n"
+            "    \"some reference\";\n"
+            "}\n";
+    char *compiled = "module a {\n"
+            "  yang-version 1.1;\n"
+            "  namespace \"urn:test:a\";\n"
+            "  prefix a;\n\n"
+            "  import ietf-yang-types {\n"
+            "    prefix yt;\n"
+            "    revision-date 2013-07-15;\n"
+            "  }\n\n"
+            "  organization\n"
+            "    \"ORG\";\n"
+            "  contact\n"
+            "    \"Radek Krejci.\";\n"
+            "  description\n"
+            "    \"Long multiline\n"
+            "      description.\";\n"
+            "  reference\n"
+            "    \"some reference\";\n"
+            "}\n";
+    char *printed;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, orig, LYS_IN_YANG));
+    assert_int_equal(strlen(orig), lys_print_mem(&printed, mod, LYS_OUT_YANG, 0, 0));
+    assert_string_equal(printed, orig);
+    free(printed);
+    assert_int_equal(strlen(compiled), lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0, 0));
+    assert_string_equal(printed, compiled);
+    free(printed);
+
+    orig = "module b {\n"
+            "  yang-version 1.1;\n"
+            "  namespace \"urn:test:b\";\n"
+            "  prefix b;\n\n"
+            "  revision 2019-04-16 {\n"
+            "    description\n"
+            "      \"text\";\n"
+            "    reference\n"
+            "      \"text\";\n"
+            "  }\n"
+            "  revision 2019-04-15 {\n"
+            "    description\n"
+            "      \"initial revision\";\n"
+            "  }\n\n"
+            "  feature f1 {\n"
+            "    status current;\n"
+            "    description\n"
+            "      \"text\";\n"
+            "    reference\n"
+            "      \"text\";\n"
+            "  }\n\n"
+            "  feature f2 {\n"
+            "    if-feature \"not f1\";\n"
+            "  }\n"
+            "}\n";
+    compiled = "module b {\n"
+            "  yang-version 1.1;\n"
+            "  namespace \"urn:test:b\";\n"
+            "  prefix b;\n\n"
+            "  revision 2019-04-16;\n\n"
+            "  feature f1 {\n"
+            "    status current;\n"
+            "    description\n"
+            "      \"text\";\n"
+            "    reference\n"
+            "      \"text\";\n"
+            "  }\n\n"
+            "  feature f2 {\n"
+            "    if-feature \"not f1\";\n"
+            "  }\n"
+            "}\n";
+    assert_non_null(mod = lys_parse_mem(ctx, orig, LYS_IN_YANG));
+    assert_int_equal(strlen(orig), lys_print_mem(&printed, mod, LYS_OUT_YANG, 0, 0));
+    assert_string_equal(printed, orig);
+    free(printed);
+    assert_int_equal(strlen(compiled), lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0, 0));
+    assert_string_equal(printed, compiled);
+    free(printed);
+
+    orig = compiled ="module c {\n"
+            "  yang-version 1.1;\n"
+            "  namespace \"urn:test:c\";\n"
+            "  prefix c;\n\n"
+            "  feature f1;\n\n"
+            "  identity i1 {\n"
+            "    if-feature \"f1\";\n"
+            "    description\n"
+            "      \"text\";\n"
+            "    reference\n"
+            "      \"text32\";\n"
+            "  }\n\n"
+            "  identity i2 {\n"
+            "    base i1;\n"
+            "    status obsolete;\n"
+            "  }\n"
+            "}\n";
+    assert_non_null(mod = lys_parse_mem(ctx, orig, LYS_IN_YANG));
+    assert_int_equal(strlen(orig), lys_print_mem(&printed, mod, LYS_OUT_YANG, 0, 0));
+    assert_string_equal(printed, orig);
+    free(printed);
+    assert_int_equal(strlen(compiled), lys_print_mem(&printed, mod, LYS_OUT_YANG, 0, 0));
+    assert_string_equal(printed, compiled);
+    free(printed);
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+/* TODO: include */
+
+int main(void)
+{
+    const struct CMUnitTest tests[] = {
+        cmocka_unit_test_setup_teardown(test_module, logger_setup, logger_teardown),
+    };
+
+    return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/utests/schema/test_printer_yin.c b/tests/utests/schema/test_printer_yin.c
new file mode 100644
index 0000000..2ffa611
--- /dev/null
+++ b/tests/utests/schema/test_printer_yin.c
@@ -0,0 +1,606 @@
+/*
+ * @file test_printer_yin.c
+ * @author: Fred Gan <ganshaolong@vip.qq.com>
+ * @brief unit tests for functions from printer_yin.c
+ *
+ * Copyright (c) 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 <setjmp.h>
+#include <cmocka.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../../src/context.h"
+#include "../../src/printer_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 */
+#if ENABLE_LOGGER_CHECKING
+    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
+
+
+static void
+test_module(void **state)
+{
+    *state = test_module;
+
+    struct ly_ctx *ctx = {0};
+    const struct lys_module *mod;
+
+    const char * orig =
+            "module all {\n"
+            "    yang-version 1.1;\n"
+            "    namespace \"urn:all\";\n"
+            "    prefix all_mod;\n\n"
+            "    import ietf-yang-types {\n"
+            "        prefix yt;\n"
+            "        revision-date 2013-07-15;\n"
+            "        description\n"
+            "            \"YANG types\";\n"
+            "        reference\n"
+            "            \"RFC reference\";\n"
+            "    }\n\n"
+            "    feature feat1 {\n"
+            "        if-feature \"feat2\";\n"
+            "        status obsolete;\n"
+            "    }\n\n"
+            "    feature feat2;\n"
+            "    feature feat3;\n\n"
+            "    identity ident2 {\n"
+            "        base ident1;\n"
+            "    }\n\n"
+            "    identity ident1;\n\n"
+            "    typedef tdef1 {\n"
+            "        type tdef2 {\n"
+            "            length \"3..9 | 30..40\";\n"
+            "            pattern \"[ac]*\";\n"
+            "        }\n"
+            "        units \"none\";\n"
+            "        default \"aaa\";\n"
+            "    }\n\n"
+            "    typedef tdef2 {\n"
+            "        type string {\n"
+            "            length \"2..10 | 20..50\";\n"
+            "            pattern \"[ab]*\";\n"
+            "        }\n"
+            "    }\n\n"
+            "    grouping group1 {\n"
+            "        leaf leaf1 {\n"
+            "            type int8;\n"
+            "        }\n"
+            "    }\n\n"
+            "    container cont1 {\n"
+            "        leaf leaf2 {\n"
+            "            if-feature \"feat1\";\n"
+            "            type int16;\n"
+            "            status obsolete;\n"
+            "        }\n\n"
+            "        uses group1 {\n"
+            "            if-feature \"feat2\";\n"
+            "            refine \"leaf1\" {\n"
+            "                if-feature \"feat3\";\n"
+            "                must \"24 - 4 = number('20')\";\n"
+            "                default \"25\";\n"
+            "                config true;\n"
+            "                mandatory false;\n"
+            "                description\n"
+            "                    \"dsc\";\n"
+            "                reference\n"
+            "                    \"none\";\n"
+            "            }\n"
+            "        }\n\n"
+            "        leaf leaf3 {\n"
+            "            type int32;\n"
+            "        }\n\n"
+            "        leaf leaf4 {\n"
+            "            type int64 {\n"
+            "                range \"1000 .. 50000\" {\n"
+            "                    error-message\n"
+            "                        \"Special error message.\";\n"
+            "                    error-app-tag \"special-tag\";\n"
+            "                }\n"
+            "            }\n"
+            "        }\n\n"
+            "        leaf leaf5 {\n"
+            "            type uint8;\n"
+            "        }\n\n"
+            "        leaf leaf6 {\n"
+            "            type uint16;\n"
+            "        }\n\n"
+            "        leaf leaf7 {\n"
+            "            type uint32;\n"
+            "        }\n\n"
+            "        leaf leaf8 {\n"
+            "            type uint64;\n"
+            "        }\n\n"
+            "        choice choic1 {\n"
+            "            default \"leaf9b\";\n"
+            "            leaf leaf9a {\n"
+            "                type decimal64 {\n"
+            "                    fraction-digits 9;\n"
+            "                }\n"
+            "            }\n\n"
+            "            leaf leaf9b {\n"
+            "                type boolean;\n"
+            "                default \"false\";\n"
+            "            }\n"
+            "        }\n\n"
+            "        leaf leaf10 {\n"
+            "            type boolean;\n"
+            "        }\n\n"
+            "        leaf leaf11 {\n"
+            "            type enumeration {\n"
+            "                enum \"one\";\n"
+            "                enum \"two\";\n"
+            "                enum \"five\" {\n"
+            "                    value 5;\n"
+            "                }\n"
+            "            }\n"
+            "        }\n\n"
+            "        leaf leaf12 {\n"
+            "            type bits {\n"
+            "                bit flag0 {\n"
+            "                    position 0;\n"
+            "                }\n"
+            "                bit flag1;\n"
+            "                bit flag2 {\n"
+            "                    position 2;\n"
+            "                }\n"
+            "                bit flag3 {\n"
+            "                    position 3;\n"
+            "                }\n"
+            "            }\n"
+            "            default \"flag0 flag3\";\n"
+            "        }\n\n"
+            "        leaf leaf13 {\n"
+            "            type binary;\n"
+            "        }\n\n"
+            "        leaf leaf14 {\n"
+            "            type leafref {\n"
+            "                path \"/cont1/leaf17\";\n"
+            "            }\n"
+            "        }\n\n"
+            "        leaf leaf15 {\n"
+            "            type empty;\n"
+            "        }\n\n"
+            "        leaf leaf16 {\n"
+            "            type union {\n"
+            "                type instance-identifier {\n"
+            "                    require-instance true;\n"
+            "                }\n"
+            "                type int8;\n"
+            "            }\n"
+            "        }\n\n"
+            "        list list1 {\n"
+            "            key \"leaf18\";\n"
+            "            unique \"leaf19\";\n"
+            "            min-elements 1;\n"
+            "            max-elements 20;\n"
+            "            leaf leaf18 {\n"
+            "                type string;\n"
+            "            }\n\n"
+            "            leaf leaf19 {\n"
+            "                type uint32;\n"
+            "            }\n\n"
+            "            anyxml axml1;\n"
+            "            anydata adata1;\n\n"
+            "            action act1 {\n"
+            "                input {\n"
+            "                    leaf leaf24 {\n"
+            "                        type string;\n"
+            "                    }\n"
+            "                }\n\n"
+            "                output {\n"
+            "                    leaf leaf25 {\n"
+            "                        type string;\n"
+            "                    }\n"
+            "                }\n"
+            "            }\n\n"
+            "            notification notif1 {\n"
+            "                leaf leaf26 {\n"
+            "                    type string;\n"
+            "                }\n"
+            "            }\n"
+            "        }\n\n"
+            "        leaf-list llist1 {\n"
+            "            type tdef1;\n"
+            "            ordered-by user;\n"
+            "        }\n\n"
+            "        list list2 {\n"
+            "            key \"leaf27 leaf28\";\n"
+            "            leaf leaf27 {\n"
+            "                type uint8;\n"
+            "            }\n\n"
+            "            leaf leaf28 {\n"
+            "                type uint8;\n"
+            "            }\n"
+            "        }\n\n"
+            "        leaf leaf29 {\n"
+            "            type instance-identifier;\n"
+            "        }\n\n"
+            "        container must-deviations-container {\n"
+            "            presence \"Allows deviations on the leaf\";\n"
+            "            leaf leaf30 {\n"
+            "                type string;\n"
+            "            }\n"
+            "        }\n\n"
+            "        leaf leaf23 {\n"
+            "            type empty;\n"
+            "        }\n"
+            "    }\n\n"
+            "    augment \"/cont1\" {\n"
+            "        leaf leaf17 {\n"
+            "            type string;\n"
+            "        }\n"
+            "    }\n\n"
+            "    rpc rpc1 {\n"
+            "        input {\n"
+            "            leaf leaf20 {\n"
+            "                type tdef1;\n"
+            "            }\n"
+            "        }\n\n"
+            "        output {\n"
+            "            container cont2 {\n"
+            "                leaf leaf21 {\n"
+            "                    type empty;\n"
+            "                }\n"
+            "            }\n"
+            "        }\n"
+            "    }\n\n"
+            "    container test-when {\n"
+            "        leaf when-check {\n"
+            "            type boolean;\n"
+            "        }\n\n"
+            "        leaf gated-data {\n"
+            "            when \"../when-check = 'true'\";\n"
+            "            type uint16;\n"
+            "        }\n"
+            "    }\n\n"
+            "    extension c-define {\n"
+            "        description\n"
+            "            \"Takes as an argument a name string.\n"
+            "            Makes the code generator use the given name\n"
+            "            in the #define.\";\n"
+            "        argument \"name\";\n"
+            "    }\n"
+            "}\n";
+
+
+    const char * ori_res =
+            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            "<module name=\"all\"\n"
+            "        xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
+            "        xmlns:all_mod=\"urn:all\"\n"
+            "        xmlns:yt=\"urn:ietf:params:xml:ns:yang:ietf-yang-types\">\n"
+            "  <yang-version value=\"1.1\"/>\n"
+            "  <namespace uri=\"urn:all\"/>\n"
+            "  <prefix value=\"all_mod\"/>\n"
+            "  <import module=\"ietf-yang-types\">\n"
+            "    <prefix value=\"yt\"/>\n"
+            "    <revision-date date=\"2013-07-15\"/>\n"
+            "    <description>\n"
+            "      <text>YANG types</text>\n"
+            "    </description>\n"
+            "    <reference>\n"
+            "      <text>RFC reference</text>\n"
+            "    </reference>\n"
+            "  </import>\n\n"
+            "  <extension name=\"c-define\">\n"
+            "    <argument name=\"name\"/>\n"
+            "    <description>\n"
+            "      <text>Takes as an argument a name string.\n"
+            "Makes the code generator use the given name\n"
+            "in the #define.</text>\n"
+            "    </description>\n"
+            "  </extension>\n"
+            "  <feature name=\"feat1\">\n"
+            "    <if-feature name=\"feat2\"/>\n"
+            "    <status value=\"obsolete\"/>\n"
+            "  </feature>\n"
+            "  <feature name=\"feat2\"/>\n"
+            "  <feature name=\"feat3\"/>\n"
+            "  <identity name=\"ident2\">\n"
+            "    <base name=\"ident1\"/>\n"
+            "  </identity>\n"
+            "  <identity name=\"ident1\"/>\n"
+            "  <typedef name=\"tdef1\">\n"
+            "    <type name=\"tdef2\">\n"
+            "      <length value=\"3..9 | 30..40\"/>\n"
+            "      <pattern value=\"[ac]*\"/>\n"
+            "    </type>\n"
+            "    <units name=\"none\"/>\n"
+            "    <default value=\"aaa\"/>\n"
+            "  </typedef>\n"
+            "  <typedef name=\"tdef2\">\n"
+            "    <type name=\"string\">\n"
+            "      <length value=\"2..10 | 20..50\"/>\n"
+            "      <pattern value=\"[ab]*\"/>\n"
+            "    </type>\n"
+            "  </typedef>\n"
+            "  <grouping name=\"group1\">\n"
+            "    <leaf name=\"leaf1\">\n"
+            "      <type name=\"int8\"/>\n"
+            "    </leaf>\n"
+            "  </grouping>\n"
+            "  <container name=\"cont1\">\n"
+            "    <leaf name=\"leaf2\">\n"
+            "      <if-feature name=\"feat1\"/>\n"
+            "      <type name=\"int16\"/>\n"
+            "      <status value=\"obsolete\"/>\n"
+            "    </leaf>\n"
+            "    <uses name=\"group1\">\n"
+            "      <if-feature name=\"feat2\"/>\n"
+            "      <refine target-node=\"leaf1\">\n"
+            "        <if-feature name=\"feat3\"/>\n"
+            "        <must condition=\"24 - 4 = number('20')\"/>\n"
+            "        <default value=\"25\"/>\n"
+            "        <config value=\"true\"/>\n"
+            "        <mandatory value=\"false\"/>\n"
+            "        <description>\n"
+            "          <text>dsc</text>\n"
+            "        </description>\n"
+            "        <reference>\n"
+            "          <text>none</text>\n"
+            "        </reference>\n"
+            "      </refine>\n"
+            "    </uses>\n"
+            "    <leaf name=\"leaf3\">\n"
+            "      <type name=\"int32\"/>\n"
+            "    </leaf>\n"
+            "    <leaf name=\"leaf4\">\n"
+            "      <type name=\"int64\">\n"
+            "        <range value=\"1000 .. 50000\">\n"
+            "          <error-message>\n"
+            "            <value>Special error message.</value>\n"
+            "          </error-message>\n"
+            "          <error-app-tag value=\"special-tag\"/>\n"
+            "        </range>\n"
+            "      </type>\n"
+            "    </leaf>\n"
+            "    <leaf name=\"leaf5\">\n"
+            "      <type name=\"uint8\"/>\n"
+            "    </leaf>\n"
+            "    <leaf name=\"leaf6\">\n"
+            "      <type name=\"uint16\"/>\n"
+            "    </leaf>\n"
+            "    <leaf name=\"leaf7\">\n"
+            "      <type name=\"uint32\"/>\n"
+            "    </leaf>\n"
+            "    <leaf name=\"leaf8\">\n"
+            "      <type name=\"uint64\"/>\n"
+            "    </leaf>\n"
+            "    <choice name=\"choic1\">\n"
+            "      <default value=\"leaf9b\"/>\n"
+            "      <leaf name=\"leaf9a\">\n"
+            "        <type name=\"decimal64\">\n"
+            "          <fraction-digits value=\"9\"/>\n"
+            "        </type>\n"
+            "      </leaf>\n"
+            "      <leaf name=\"leaf9b\">\n"
+            "        <type name=\"boolean\"/>\n"
+            "        <default value=\"false\"/>\n"
+            "      </leaf>\n"
+            "    </choice>\n"
+            "    <leaf name=\"leaf10\">\n"
+            "      <type name=\"boolean\"/>\n"
+            "    </leaf>\n"
+            "    <leaf name=\"leaf11\">\n"
+            "      <type name=\"enumeration\">\n"
+            "        <enum name=\"one\"/>\n"
+            "        <enum name=\"two\"/>\n"
+            "        <enum name=\"five\">\n"
+            "          <value value=\"5\"/>\n"
+            "        </enum>\n"
+            "      </type>\n"
+            "    </leaf>\n"
+            "    <leaf name=\"leaf12\">\n"
+            "      <type name=\"bits\">\n"
+            "        <bit name=\"flag0\">\n"
+            "          <position value=\"0\"/>\n"
+            "        </bit>\n"
+            "        <bit name=\"flag1\"/>\n"
+            "        <bit name=\"flag2\">\n"
+            "          <position value=\"2\"/>\n"
+            "        </bit>\n"
+            "        <bit name=\"flag3\">\n"
+            "          <position value=\"3\"/>\n"
+            "        </bit>\n"
+            "      </type>\n"
+            "      <default value=\"flag0 flag3\"/>\n"
+            "    </leaf>\n"
+            "    <leaf name=\"leaf13\">\n"
+            "      <type name=\"binary\"/>\n"
+            "    </leaf>\n"
+            "    <leaf name=\"leaf14\">\n"
+            "      <type name=\"leafref\">\n"
+            "        <path value=\"/cont1/leaf17\"/>\n"
+            "      </type>\n"
+            "    </leaf>\n"
+            "    <leaf name=\"leaf15\">\n"
+            "      <type name=\"empty\"/>\n"
+            "    </leaf>\n"
+            "    <leaf name=\"leaf16\">\n"
+            "      <type name=\"union\">\n"
+            "        <type name=\"instance-identifier\">\n"
+            "          <require-instance value=\"true\"/>\n"
+            "        </type>\n"
+            "        <type name=\"int8\"/>\n"
+            "      </type>\n"
+            "    </leaf>\n"
+            "    <list name=\"list1\">\n"
+            "      <key value=\"leaf18\"/>\n"
+            "      <unique tag=\"leaf19\"/>\n"
+            "      <min-elements value=\"1\"/>\n"
+            "      <max-elements value=\"20\"/>\n"
+            "      <leaf name=\"leaf18\">\n"
+            "        <type name=\"string\"/>\n"
+            "      </leaf>\n"
+            "      <leaf name=\"leaf19\">\n"
+            "        <type name=\"uint32\"/>\n"
+            "      </leaf>\n"
+            "      <anyxml name=\"axml1\"/>\n"
+            "      <anydata name=\"adata1\"/>\n"
+            "      <action name=\"act1\">\n"
+            "        <input>\n"
+            "          <leaf name=\"leaf24\">\n"
+            "            <type name=\"string\"/>\n"
+            "          </leaf>\n"
+            "        </input>\n"
+            "        <output>\n"
+            "          <leaf name=\"leaf25\">\n"
+            "            <type name=\"string\"/>\n"
+            "          </leaf>\n"
+            "        </output>\n"
+            "      </action>\n"
+            "      <notification name=\"notif1\">\n"
+            "        <leaf name=\"leaf26\">\n"
+            "          <type name=\"string\"/>\n"
+            "        </leaf>\n"
+            "      </notification>\n"
+            "    </list>\n"
+            "    <leaf-list name=\"llist1\">\n"
+            "      <type name=\"tdef1\"/>\n"
+            "      <ordered-by value=\"user\"/>\n"
+            "    </leaf-list>\n"
+            "    <list name=\"list2\">\n"
+            "      <key value=\"leaf27 leaf28\"/>\n"
+            "      <leaf name=\"leaf27\">\n"
+            "        <type name=\"uint8\"/>\n"
+            "      </leaf>\n"
+            "      <leaf name=\"leaf28\">\n"
+            "        <type name=\"uint8\"/>\n"
+            "      </leaf>\n"
+            "    </list>\n"
+            "    <leaf name=\"leaf29\">\n"
+            "      <type name=\"instance-identifier\"/>\n"
+            "    </leaf>\n"
+            "    <container name=\"must-deviations-container\">\n"
+            "      <presence value=\"Allows deviations on the leaf\"/>\n"
+            "      <leaf name=\"leaf30\">\n"
+            "        <type name=\"string\"/>\n"
+            "      </leaf>\n"
+            "    </container>\n"
+            "    <leaf name=\"leaf23\">\n"
+            "      <type name=\"empty\"/>\n"
+            "    </leaf>\n"
+            "  </container>\n"
+            "  <container name=\"test-when\">\n"
+            "    <leaf name=\"when-check\">\n"
+            "      <type name=\"boolean\"/>\n"
+            "    </leaf>\n"
+            "    <leaf name=\"gated-data\">\n"
+            "      <when condition=\"../when-check = 'true'\"/>\n"
+            "      <type name=\"uint16\"/>\n"
+            "    </leaf>\n"
+            "  </container>\n"
+            "  <augment target-node=\"/cont1\">\n"
+            "    <leaf name=\"leaf17\">\n"
+            "      <type name=\"string\"/>\n"
+            "    </leaf>\n"
+            "  </augment>\n"
+            "  <rpc name=\"rpc1\">\n"
+            "    <input>\n"
+            "      <leaf name=\"leaf20\">\n"
+            "        <type name=\"tdef1\"/>\n"
+            "      </leaf>\n"
+            "    </input>\n"
+            "    <output>\n"
+            "      <container name=\"cont2\">\n"
+            "        <leaf name=\"leaf21\">\n"
+            "          <type name=\"empty\"/>\n"
+            "        </leaf>\n"
+            "      </container>\n"
+            "    </output>\n"
+            "  </rpc>\n"
+            "</module>\n";
+
+    char * printed;
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, orig, LYS_IN_YANG));
+    assert_int_equal(strlen(ori_res), lys_print_mem(&printed, mod, LYS_OUT_YIN, 0, 0));
+    assert_string_equal(printed, ori_res);
+    free(printed);
+    /*
+    assert_int_equal(strlen(compiled), lys_print_mem(&printed, mod, LYS_OUT_YANG_COMPILED, 0, 0));
+    assert_string_equal(printed, compiled);
+    free(printed);
+    */
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+int main(void)
+{
+    const struct CMUnitTest tests[] = {
+        cmocka_unit_test_setup_teardown(test_module, logger_setup, logger_teardown),
+    };
+
+    return cmocka_run_group_tests(tests, NULL, NULL);
+}
+
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/schema/test_tree_schema_compile.c b/tests/utests/schema/test_tree_schema_compile.c
new file mode 100644
index 0000000..81d13bb
--- /dev/null
+++ b/tests/utests/schema/test_tree_schema_compile.c
@@ -0,0 +1,3351 @@
+/*
+ * @file test_parser_yang.c
+ * @author: Radek Krejci <rkrejci@cesnet.cz>
+ * @brief unit tests for functions from parser_yang.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 <setjmp.h>
+#include <cmocka.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../../src/common.h"
+#include "../../src/tree_schema_internal.h"
+#include "../../src/xpath.h"
+#include "../../src/plugins_types.h"
+
+void lysc_feature_free(struct ly_ctx *ctx, struct lysc_feature *feat);
+void yang_parser_ctx_free(struct lys_yang_parser_ctx *ctx);
+
+LY_ERR lys_path_token(const char **path, const char **prefix, size_t *prefix_len, const char **name, size_t *name_len,
+                      int *parent_times, int *has_predicate);
+
+#define BUFSIZE 1024
+char logbuf[BUFSIZE] = {0};
+
+/* 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 (path && path[0]) {
+        snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
+    } else {
+        strncpy(logbuf, msg, BUFSIZE - 1);
+    }
+}
+#endif
+
+static int
+logger_setup(void **state)
+{
+    (void) state; /* unused */
+#if ENABLE_LOGGER_CHECKING
+    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);logbuf_clean()
+#else
+#   define logbuf_assert(str)
+#endif
+
+static LY_ERR test_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const char *UNUSED(submod_name),
+                           const char *UNUSED(sub_rev), void *user_data, LYS_INFORMAT *format,
+                           const char **module_data, void (**free_module_data)(void *model_data, void *user_data))
+{
+    *module_data = user_data;
+    *format = LYS_IN_YANG;
+    *free_module_data = NULL;
+    return LY_SUCCESS;
+}
+
+static void
+reset_mod(struct lys_module *module)
+{
+    struct ly_ctx *ctx = module->ctx;
+    lysc_module_free(module->compiled, NULL);
+    lysp_module_free(module->parsed);
+
+    FREE_STRING(ctx, module->name);
+    FREE_STRING(ctx, module->ns);
+    FREE_STRING(ctx, module->prefix);
+    FREE_STRING(ctx, module->filepath);
+    FREE_STRING(ctx, module->org);
+    FREE_STRING(ctx, module->contact);
+    FREE_STRING(ctx, module->dsc);
+    FREE_STRING(ctx, module->ref);
+    FREE_ARRAY(ctx, module->off_features, lysc_feature_free);
+
+    memset(module, 0, sizeof *module);
+    module->ctx = ctx;
+    module->implemented = 1;
+}
+
+static void
+test_module(void **state)
+{
+    *state = test_module;
+
+    const char *str;
+    struct lys_yang_parser_ctx *ctx = NULL;
+    struct lys_module mod = {0};
+    struct lysc_feature *f;
+    struct lysc_iffeature *iff;
+
+    str = "module test {namespace urn:test; prefix t;"
+          "feature f1;feature f2 {if-feature f1;}}";
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &mod.ctx));
+    reset_mod(&mod);
+
+    assert_int_equal(LY_EINVAL, lys_compile(NULL, 0));
+    logbuf_assert("Invalid argument mod (lys_compile()).");
+    assert_int_equal(LY_EINVAL, lys_compile(&mod, 0));
+    logbuf_assert("Invalid argument mod->parsed (lys_compile()).");
+    assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, str, &mod));
+    yang_parser_ctx_free(ctx);
+    mod.implemented = 0;
+    assert_int_equal(LY_SUCCESS, lys_compile(&mod, 0));
+    assert_null(mod.compiled);
+    mod.implemented = 1;
+    assert_int_equal(LY_SUCCESS, lys_compile(&mod, 0));
+    assert_non_null(mod.compiled);
+    assert_string_equal("test", mod.name);
+    assert_string_equal("urn:test", mod.ns);
+    assert_string_equal("t", mod.prefix);
+    /* features */
+    assert_non_null(mod.compiled->features);
+    assert_int_equal(2, LY_ARRAY_SIZE(mod.compiled->features));
+    f = &mod.compiled->features[1];
+    assert_non_null(f->iffeatures);
+    assert_int_equal(1, LY_ARRAY_SIZE(f->iffeatures));
+    iff = &f->iffeatures[0];
+    assert_non_null(iff->expr);
+    assert_non_null(iff->features);
+    assert_int_equal(1, LY_ARRAY_SIZE(iff->features));
+    assert_ptr_equal(&mod.compiled->features[0], iff->features[0]);
+
+    lysc_module_free(mod.compiled, NULL);
+
+    assert_int_equal(LY_SUCCESS, lys_compile(&mod, LYSC_OPT_FREE_SP));
+    assert_non_null(mod.compiled);
+
+    lysc_module_free(mod.compiled, NULL);
+    mod.compiled = NULL;
+
+    /* submodules cannot be compiled directly */
+    str = "submodule test {belongs-to xxx {prefix x;}}";
+    assert_int_equal(LY_EINVAL, yang_parse_module(&ctx, str, &mod));
+    yang_parser_ctx_free(ctx);
+    logbuf_assert("Input data contains submodule which cannot be parsed directly without its main module.");
+    assert_null(mod.parsed);
+    reset_mod(&mod);
+
+    /* data definition name collision in top level */
+    assert_int_equal(LY_SUCCESS, yang_parse_module(&ctx, "module aa {namespace urn:aa;prefix aa;"
+                                                  "leaf a {type string;} container a{presence x;}}", &mod));
+    yang_parser_ctx_free(ctx);
+    assert_int_equal(LY_EVALID, lys_compile(&mod, 0));
+    logbuf_assert("Duplicate identifier \"a\" of data definition/RPC/action/notification statement. /aa:a");
+    assert_null(mod.compiled);
+    reset_mod(&mod);
+
+    *state = NULL;
+    ly_ctx_destroy(mod.ctx, NULL);
+}
+
+
+
+static void
+test_node_container(void **state)
+{
+    (void) state; /* unused */
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_node_container *cont;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;container c;}", LYS_IN_YANG));
+    assert_non_null(mod->compiled);
+    assert_non_null((cont = (struct lysc_node_container*)mod->compiled->data));
+    assert_int_equal(LYS_CONTAINER, cont->nodetype);
+    assert_string_equal("c", cont->name);
+    assert_true(cont->flags & LYS_CONFIG_W);
+    assert_true(cont->flags & LYS_STATUS_CURR);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;container c {config false; status deprecated; container child;}}", LYS_IN_YANG));
+    logbuf_assert("Missing explicit \"deprecated\" status that was already specified in parent, inheriting.");
+    assert_non_null(mod->compiled);
+    assert_non_null((cont = (struct lysc_node_container*)mod->compiled->data));
+    assert_true(cont->flags & LYS_CONFIG_R);
+    assert_true(cont->flags & LYS_STATUS_DEPRC);
+    assert_non_null((cont = (struct lysc_node_container*)cont->child));
+    assert_int_equal(LYS_CONTAINER, cont->nodetype);
+    assert_true(cont->flags & LYS_CONFIG_R);
+    assert_true(cont->flags & LYS_STATUS_DEPRC);
+    assert_string_equal("child", cont->name);
+
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_node_leaflist(void **state)
+{
+    *state = test_node_leaflist;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_type *type;
+    struct lysc_node_leaflist *ll;
+    struct lysc_node_leaf *l;
+    const char *dflt;
+    int dynamic;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;"
+                                        "typedef mytype {type union {type leafref {path ../target;} type string;}}"
+                                        "leaf-list ll1 {type union {type decimal64 {fraction-digits 2;} type mytype;}}"
+                                        "leaf-list ll2 {type leafref {path ../target;}}"
+                                        "leaf target {type int8;}}",
+                                        LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_UNION, type->basetype);
+    assert_non_null(((struct lysc_type_union*)type)->types);
+    assert_int_equal(3, LY_ARRAY_SIZE(((struct lysc_type_union*)type)->types));
+    assert_int_equal(LY_TYPE_DEC64, ((struct lysc_type_union*)type)->types[0]->basetype);
+    assert_int_equal(LY_TYPE_LEAFREF, ((struct lysc_type_union*)type)->types[1]->basetype);
+    assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_union*)type)->types[2]->basetype);
+    assert_non_null(((struct lysc_type_leafref*)((struct lysc_type_union*)type)->types[1])->realtype);
+    assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_leafref*)((struct lysc_type_union*)type)->types[1])->realtype->basetype);
+    type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+    assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_leafref*)type)->realtype->basetype);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;leaf-list ll {type string;}}", LYS_IN_YANG));
+    assert_non_null(mod->compiled);
+    assert_non_null((ll = (struct lysc_node_leaflist*)mod->compiled->data));
+    assert_int_equal(0, ll->min);
+    assert_int_equal((uint32_t)-1, ll->max);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module c {yang-version 1.1;namespace urn:c;prefix c;typedef mytype {type int8;default 10;}"
+                                        "leaf-list ll1 {type mytype;default 1; default 1; config false;}"
+                                        "leaf-list ll2 {type mytype; ordered-by user;}}", LYS_IN_YANG));
+    assert_non_null(mod->compiled);
+    assert_non_null((ll = (struct lysc_node_leaflist*)mod->compiled->data));
+    assert_non_null(ll->dflts);
+    assert_int_equal(6, ll->type->refcount); /* 3x type's reference, 3x default value's reference (typedef's default does not reference own type) */
+    assert_int_equal(2, LY_ARRAY_SIZE(ll->dflts));
+    assert_string_equal("1", dflt = ll->dflts[0]->realtype->plugin->print(ll->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_string_equal("1", dflt = ll->dflts[1]->realtype->plugin->print(ll->dflts[1], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM | LYS_SET_DFLT | LYS_SET_CONFIG, ll->flags);
+    assert_non_null((ll = (struct lysc_node_leaflist*)mod->compiled->data->next));
+    assert_non_null(ll->dflts);
+    assert_int_equal(6, ll->type->refcount); /* 3x type's reference, 3x default value's reference */
+    assert_int_equal(1, LY_ARRAY_SIZE(ll->dflts));
+    assert_string_equal("10", dflt = ll->dflts[0]->realtype->plugin->print(ll->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_USER, ll->flags);
+
+    /* ordered-by is ignored for state data, RPC/action output parameters and notification content */
+    assert_non_null(mod = lys_parse_mem(ctx, "module d {yang-version 1.1;namespace urn:d;prefix d;"
+                                        "leaf-list ll {config false; type string; ordered-by user;}}", LYS_IN_YANG));
+    /* but warning is present: */
+    logbuf_assert("The ordered-by statement is ignored in lists representing state data (/d:ll).");
+    assert_non_null(mod->compiled);
+    assert_non_null((ll = (struct lysc_node_leaflist*)mod->compiled->data));
+    assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM | LYS_SET_CONFIG, ll->flags);
+    logbuf_clean();
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module e {yang-version 1.1;namespace urn:e;prefix e;"
+                                        "rpc oper {output {leaf-list ll {type string; ordered-by user;}}}}", LYS_IN_YANG));
+    logbuf_assert("The ordered-by statement is ignored in lists representing RPC/action output parameters (/e:oper/output/ll).");
+    logbuf_clean();
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module f {yang-version 1.1;namespace urn:f;prefix f;"
+                                        "notification event {leaf-list ll {type string; ordered-by user;}}}", LYS_IN_YANG));
+    logbuf_assert("The ordered-by statement is ignored in lists representing notification content (/f:event/ll).");
+
+    /* forward reference in default */
+    assert_non_null(mod = lys_parse_mem(ctx, "module g {yang-version 1.1; namespace urn:g;prefix g;"
+                                        "leaf ref {type instance-identifier {require-instance true;} default \"/g:g\";}"
+                                        "leaf-list g {type string;}}", LYS_IN_YANG));
+    assert_non_null(l = (struct lysc_node_leaf*)mod->compiled->data);
+    assert_string_equal("ref", l->name);
+    assert_non_null(l->dflt);
+    assert_null(l->dflt->canonical_cache);
+
+    /* invalid */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;leaf-list ll {type empty;}}", LYS_IN_YANG));
+    logbuf_assert("Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules. /aa:ll");
+
+    assert_null(lys_parse_mem(ctx, "module bb {yang-version 1.1;namespace urn:bb;prefix bb;leaf-list ll {type empty; default x;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid leaf-lists's default value \"x\" which does not fit the type (Invalid empty value \"x\".). /bb:ll");
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module cc {yang-version 1.1;namespace urn:cc;prefix cc;"
+                                        "leaf-list ll {config false;type string; default one;default two;default one;}}", LYS_IN_YANG));
+    assert_non_null(mod->compiled);
+    assert_non_null((ll = (struct lysc_node_leaflist*)mod->compiled->data));
+    assert_non_null(ll->dflts);
+    assert_int_equal(3, LY_ARRAY_SIZE(ll->dflts));
+    assert_null(lys_parse_mem(ctx, "module dd {yang-version 1.1;namespace urn:dd;prefix dd;"
+                              "leaf-list ll {type string; default one;default two;default one;}}", LYS_IN_YANG));
+    logbuf_assert("Configuration leaf-list has multiple defaults of the same value \"one\". /dd:ll");
+
+    assert_null(lys_parse_mem(ctx, "module ee {yang-version 1.1; namespace urn:ee;prefix ee;"
+                              "leaf ref {type instance-identifier {require-instance true;} default \"/ee:g\";}}", LYS_IN_YANG));
+    logbuf_assert("Invalid default - value does not fit the type "
+                  "(Invalid instance-identifier \"/ee:g\" value - path \"/ee:g\" does not exists in the YANG schema.). /ee:ref");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_node_list(void **state)
+{
+    *state = test_node_list;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_node_list *list;
+    struct lysc_node *child;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;feature f;"
+                                        "list l1 {key \"x y\"; ordered-by user; leaf y{type string;if-feature f;} leaf x {type string; when 1;}}"
+                                        "list l2 {config false;leaf value {type string;}}}", LYS_IN_YANG));
+    list = (struct lysc_node_list*)mod->compiled->data;
+    assert_non_null(list);
+    assert_non_null(list->child);
+    assert_string_equal("x", list->child->name);
+    assert_true(list->child->flags & LYS_KEY);
+    assert_string_equal("y", list->child->next->name);
+    assert_true(list->child->next->flags & LYS_KEY);
+    assert_non_null(list->child);
+    assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_USER, list->flags);
+    assert_true(list->child->flags & LYS_KEY);
+    assert_true(list->child->next->flags & LYS_KEY);
+    list = (struct lysc_node_list*)mod->compiled->data->next;
+    assert_non_null(list);
+    assert_non_null(list->child);
+    assert_false(list->child->flags & LYS_KEY);
+    assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM | LYS_SET_CONFIG | LYS_KEYLESS, list->flags);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;"
+                                        "list l {key a; unique \"a c/b:b\"; unique \"c/e d\";"
+                                        "leaf a {type string; default x;} leaf d {type string;config false;}"
+                                        "container c {leaf b {type string;}leaf e{type string;config false;}}}}", LYS_IN_YANG));
+    list = (struct lysc_node_list*)mod->compiled->data;
+    assert_non_null(list);
+    assert_string_equal("l", list->name);
+    assert_string_equal("a", list->child->name);
+    assert_true(list->child->flags & LYS_KEY);
+    assert_null(((struct lysc_node_leaf*)list->child)->dflt);
+    assert_non_null(list->uniques);
+    assert_int_equal(2, LY_ARRAY_SIZE(list->uniques));
+    assert_int_equal(2, LY_ARRAY_SIZE(list->uniques[0]));
+    assert_string_equal("a", list->uniques[0][0]->name);
+    assert_true(list->uniques[0][0]->flags & LYS_UNIQUE);
+    assert_string_equal("b", list->uniques[0][1]->name);
+    assert_true(list->uniques[0][1]->flags & LYS_UNIQUE);
+    assert_int_equal(2, LY_ARRAY_SIZE(list->uniques[1]));
+    assert_string_equal("e", list->uniques[1][0]->name);
+    assert_true(list->uniques[1][0]->flags & LYS_UNIQUE);
+    assert_string_equal("d", list->uniques[1][1]->name);
+    assert_true(list->uniques[1][1]->flags & LYS_UNIQUE);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module c {yang-version 1.1;namespace urn:c;prefix c;"
+                                        "list l {key a;leaf a {type empty;}}}", LYS_IN_YANG));
+    list = (struct lysc_node_list*)mod->compiled->data;
+    assert_non_null(list);
+    assert_string_equal("l", list->name);
+    assert_string_equal("a", list->child->name);
+    assert_true(list->child->flags & LYS_KEY);
+    assert_int_equal(LY_TYPE_EMPTY, ((struct lysc_node_leaf*)list->child)->type->basetype);
+
+    /* keys order */
+    assert_non_null(mod = lys_parse_mem(ctx, "module d {yang-version 1.1;namespace urn:d;prefix d;"
+                                        "list l {key \"d b c\";leaf a {type string;} leaf b {type string;} leaf c {type string;} leaf d {type string;}}}", LYS_IN_YANG));
+    list = (struct lysc_node_list*)mod->compiled->data;
+    assert_non_null(list);
+    assert_string_equal("l", list->name);
+    assert_non_null(child = list->child);
+    assert_string_equal("d", child->name);
+    assert_true(child->flags & LYS_KEY);
+    assert_non_null(child = child->next);
+    assert_string_equal("b", child->name);
+    assert_true(child->flags & LYS_KEY);
+    assert_non_null(child = child->next);
+    assert_string_equal("c", child->name);
+    assert_true(child->flags & LYS_KEY);
+    assert_non_null(child = child->next);
+    assert_string_equal("a", child->name);
+    assert_false(child->flags & LYS_KEY);
+
+    /* invalid */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;list l;}", LYS_IN_YANG));
+    logbuf_assert("Missing key in list representing configuration data. /aa:l");
+
+    assert_null(lys_parse_mem(ctx, "module bb {yang-version 1.1; namespace urn:bb;prefix bb;"
+                              "list l {key x; leaf x {type string; when 1;}}}", LYS_IN_YANG));
+    logbuf_assert("List's key must not have any \"when\" statement. /bb:l/x");
+
+    assert_null(lys_parse_mem(ctx, "module cc {yang-version 1.1;namespace urn:cc;prefix cc;feature f;"
+                              "list l {key x; leaf x {type string; if-feature f;}}}", LYS_IN_YANG));
+    logbuf_assert("List's key must not have any \"if-feature\" statement. /cc:l/x");
+
+    assert_null(lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;"
+                              "list l {key x; leaf x {type string; config false;}}}", LYS_IN_YANG));
+    logbuf_assert("Key of the configuration list must not be status leaf. /dd:l/x");
+
+    assert_null(lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;"
+                              "list l {config false;key x; leaf x {type string; config true;}}}", LYS_IN_YANG));
+    logbuf_assert("Configuration node cannot be child of any state data node. /ee:l/x");
+
+    assert_null(lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;"
+                              "list l {key x; leaf-list x {type string;}}}", LYS_IN_YANG));
+    logbuf_assert("The list's key \"x\" not found. /ff:l");
+
+    assert_null(lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;"
+                              "list l {key x; unique y;leaf x {type string;} leaf-list y {type string;}}}", LYS_IN_YANG));
+    logbuf_assert("Unique's descendant-schema-nodeid \"y\" refers to leaf-list node instead of a leaf. /gg:l");
+
+    assert_null(lys_parse_mem(ctx, "module hh {namespace urn:hh;prefix hh;"
+                              "list l {key x; unique \"x y\";leaf x {type string;} leaf y {config false; type string;}}}", LYS_IN_YANG));
+    logbuf_assert("Unique statement \"x y\" refers to leaves with different config type. /hh:l");
+
+    assert_null(lys_parse_mem(ctx, "module ii {namespace urn:ii;prefix ii;"
+                              "list l {key x; unique a:x;leaf x {type string;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid descendant-schema-nodeid value \"a:x\" - prefix \"a\" not defined in module \"ii\". /ii:l");
+
+    assert_null(lys_parse_mem(ctx, "module jj {namespace urn:jj;prefix jj;"
+                              "list l {key x; unique c/x;leaf x {type string;}container c {leaf y {type string;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid descendant-schema-nodeid value \"c/x\" - target node not found. /jj:l");
+
+    assert_null( lys_parse_mem(ctx, "module kk {namespace urn:kk;prefix kk;"
+                               "list l {key x; unique c^y;leaf x {type string;}container c {leaf y {type string;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid descendant-schema-nodeid value \"c^\" - missing \"/\" as node-identifier separator. /kk:l");
+
+    assert_null(lys_parse_mem(ctx, "module ll {namespace urn:ll;prefix ll;"
+                              "list l {key \"x y x\";leaf x {type string;}leaf y {type string;}}}", LYS_IN_YANG));
+    logbuf_assert("Duplicated key identifier \"x\". /ll:l");
+
+    assert_null(lys_parse_mem(ctx, "module mm {namespace urn:mm;prefix mm;"
+                              "list l {key x;leaf x {type empty;}}}", LYS_IN_YANG));
+    logbuf_assert("List's key cannot be of \"empty\" type until it is in YANG 1.1 module. /mm:l/x");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_node_choice(void **state)
+{
+    *state = test_node_choice;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_node_choice *ch;
+    struct lysc_node_case *cs;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;feature f;"
+                                        "choice ch {default a:b; when \"true()\"; case a {leaf a1 {type string;}leaf a2 {type string;}}"
+                                        "leaf b {type string;}}}", LYS_IN_YANG));
+    ch = (struct lysc_node_choice*)mod->compiled->data;
+    assert_non_null(ch);
+    assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR, ch->flags);
+    assert_int_equal(1, LY_ARRAY_SIZE(ch->when));
+    assert_null(ch->when[0]->context);
+    cs = ch->cases;
+    assert_non_null(cs);
+    assert_string_equal("a", cs->name);
+    assert_ptr_equal(ch, cs->parent);
+    assert_non_null(cs->child);
+    assert_string_equal("a1", cs->child->name);
+    assert_non_null(cs->child->next);
+    assert_string_equal("a2", cs->child->next->name);
+    assert_ptr_equal(cs, cs->child->parent);
+    cs = (struct lysc_node_case*)cs->next;
+    assert_non_null(cs);
+    assert_string_equal("b", cs->name);
+    assert_int_equal(LYS_STATUS_CURR | LYS_SET_DFLT, cs->flags);
+    assert_ptr_equal(ch, cs->parent);
+    assert_non_null(cs->child);
+    assert_string_equal("b", cs->child->name);
+    assert_ptr_equal(cs, cs->child->parent);
+    assert_ptr_equal(ch->cases->child->next, cs->child->prev);
+    assert_ptr_equal(ch->cases->child->next->next, cs->child);
+    assert_ptr_equal(ch->cases->child->prev, cs->child);
+    assert_ptr_equal(ch->dflt, cs);
+
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;"
+                              "choice ch {case a {leaf x {type string;}}leaf x {type string;}}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"x\" of data definition/RPC/action/notification statement. /aa:ch/x/x");
+    assert_null(lys_parse_mem(ctx, "module aa2 {namespace urn:aa2;prefix aa;"
+                              "choice ch {case a {leaf y {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"y\" of data definition/RPC/action/notification statement. /aa2:ch/b/y");
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;"
+                              "choice ch {case a {leaf x {type string;}}leaf a {type string;}}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"a\" of case statement. /bb:ch/a");
+    assert_null(lys_parse_mem(ctx, "module bb2 {namespace urn:bb2;prefix bb;"
+                              "choice ch {case b {leaf x {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"b\" of case statement. /bb2:ch/b");
+
+    assert_null(lys_parse_mem(ctx, "module ca {namespace urn:ca;prefix ca;"
+                              "choice ch {default c;case a {leaf x {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG));
+    logbuf_assert("Default case \"c\" not found. /ca:ch");
+    assert_null(lys_parse_mem(ctx, "module cb {namespace urn:cb;prefix cb; import a {prefix a;}"
+                              "choice ch {default a:a;case a {leaf x {type string;}}case b {leaf y {type string;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid default case referencing a case from different YANG module (by prefix \"a\"). /cb:ch");
+    assert_null(lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;"
+                              "choice ch {default a;case a {leaf x {mandatory true;type string;}}}}", LYS_IN_YANG));
+    logbuf_assert("Mandatory node \"x\" under the default case \"a\". /cc:ch");
+    /* TODO check with mandatory nodes from augment placed into the case */
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_node_anydata(void **state)
+{
+    *state = test_node_anydata;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_node_anydata *any;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1;namespace urn:a;prefix a;"
+                                        "anydata any {config false;mandatory true;}}", LYS_IN_YANG));
+    any = (struct lysc_node_anydata*)mod->compiled->data;
+    assert_non_null(any);
+    assert_int_equal(LYS_ANYDATA, any->nodetype);
+    assert_int_equal(LYS_CONFIG_R | LYS_STATUS_CURR | LYS_MAND_TRUE | LYS_SET_CONFIG, any->flags);
+
+    logbuf_clean();
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;"
+                                        "anyxml any;}", LYS_IN_YANG));
+    any = (struct lysc_node_anydata*)mod->compiled->data;
+    assert_non_null(any);
+    assert_int_equal(LYS_ANYXML, any->nodetype);
+    assert_int_equal(LYS_CONFIG_W | LYS_STATUS_CURR, any->flags);
+    logbuf_assert("Use of anyxml to define configuration data is not recommended."); /* warning */
+
+    /* invalid */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;anydata any;}", LYS_IN_YANG));
+    logbuf_assert("Invalid keyword \"anydata\" as a child of \"module\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_action(void **state)
+{
+    *state = test_action;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    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 {namespace urn:a;prefix a;"
+                                        "rpc a {input {leaf x {type int8;} leaf y {type int8;}} output {leaf result {type int16;}}}}", LYS_IN_YANG));
+    rpc = mod->compiled->rpcs;
+    assert_non_null(rpc);
+    assert_int_equal(1, LY_ARRAY_SIZE(rpc));
+    assert_int_equal(LYS_RPC, rpc->nodetype);
+    assert_int_equal(LYS_STATUS_CURR, rpc->flags);
+    assert_string_equal("a", rpc->name);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1; namespace urn:b;prefix b; container top {"
+                                        "action b {input {leaf x {type int8;} leaf y {type int8;}}"
+                                        "output {must \"result > 25\"; must \"/top\"; leaf result {type int16;}}}}}", LYS_IN_YANG));
+    rpc = lysc_node_actions(mod->compiled->data);
+    assert_non_null(rpc);
+    assert_int_equal(1, LY_ARRAY_SIZE(rpc));
+    assert_int_equal(LYS_ACTION, rpc->nodetype);
+    assert_int_equal(LYS_STATUS_CURR, rpc->flags);
+    assert_string_equal("b", rpc->name);
+    assert_null(rpc->input.musts);
+    assert_int_equal(2, LY_ARRAY_SIZE(rpc->output.musts));
+
+    /* invalid */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;container top {action x;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid keyword \"action\" as a child of \"container\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;leaf x{type string;} rpc x;}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"x\" of data definition/RPC/action/notification statement. /bb:x");
+    assert_null(lys_parse_mem(ctx, "module cc {yang-version 1.1; namespace urn:cc;prefix cc;container c {leaf y {type string;} action y;}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"y\" of data definition/RPC/action/notification statement. /cc:c/y");
+    assert_null(lys_parse_mem(ctx, "module dd {yang-version 1.1; namespace urn:dd;prefix dd;container c {action z; action z;}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"z\" of data definition/RPC/action/notification statement. /dd:c/z");
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule eesub {belongs-to ee {prefix ee;} notification w;}");
+    assert_null(lys_parse_mem(ctx, "module ee {yang-version 1.1; namespace urn:ee;prefix ee;include eesub; rpc w;}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"w\" of data definition/RPC/action/notification statement. /ee:w");
+
+    assert_null(lys_parse_mem(ctx, "module ff {yang-version 1.1; namespace urn:ff;prefix ff; rpc test {input {container a {leaf b {type string;}}}}"
+                              "augment /test/input/a {action invalid {input {leaf x {type string;}}}}}", LYS_IN_YANG));
+    logbuf_assert("Action \"invalid\" is placed inside another RPC/action. /ff:{augment='/test/input/a'}/invalid");
+
+    assert_null(lys_parse_mem(ctx, "module gg {yang-version 1.1; namespace urn:gg;prefix gg; notification test {container a {leaf b {type string;}}}"
+                              "augment /test/a {action invalid {input {leaf x {type string;}}}}}", LYS_IN_YANG));
+    logbuf_assert("Action \"invalid\" is placed inside notification. /gg:{augment='/test/a'}/invalid");
+
+    assert_null(lys_parse_mem(ctx, "module hh {yang-version 1.1; namespace urn:hh;prefix hh; notification test {container a {uses grp;}}"
+                              "grouping grp {action invalid {input {leaf x {type string;}}}}}", LYS_IN_YANG));
+    logbuf_assert("Action \"invalid\" is placed inside notification. /hh:test/a/{uses='grp'}/invalid");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_notification(void **state)
+{
+    *state = test_notification;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    const struct lysc_notif *notif;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;"
+                                        "notification a1 {leaf x {type int8;}} notification a2;}", LYS_IN_YANG));
+    notif = mod->compiled->notifs;
+    assert_non_null(notif);
+    assert_int_equal(2, LY_ARRAY_SIZE(notif));
+    assert_int_equal(LYS_NOTIF, notif->nodetype);
+    assert_int_equal(LYS_STATUS_CURR, notif->flags);
+    assert_string_equal("a1", notif->name);
+    assert_non_null(notif->data);
+    assert_string_equal("x", notif->data->name);
+    assert_int_equal(LYS_NOTIF, notif[1].nodetype);
+    assert_int_equal(LYS_STATUS_CURR, notif[1].flags);
+    assert_string_equal("a2", notif[1].name);
+    assert_null(notif[1].data);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1; namespace urn:b;prefix b; container top {"
+                                        "notification b1 {leaf x {type int8;}} notification b2 {must \"/top\";}}}", LYS_IN_YANG));
+    notif = lysc_node_notifs(mod->compiled->data);
+    assert_non_null(notif);
+    assert_int_equal(2, LY_ARRAY_SIZE(notif));
+    assert_int_equal(LYS_NOTIF, notif->nodetype);
+    assert_int_equal(LYS_STATUS_CURR, notif->flags);
+    assert_string_equal("b1", notif->name);
+    assert_non_null(notif->data);
+    assert_string_equal("x", notif->data->name);
+    assert_int_equal(LYS_NOTIF, notif[1].nodetype);
+    assert_int_equal(LYS_STATUS_CURR, notif[1].flags);
+    assert_string_equal("b2", notif[1].name);
+    assert_null(notif[1].data);
+    assert_int_equal(1, LY_ARRAY_SIZE(notif[1].musts));
+
+    /* invalid */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;container top {notification x;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid keyword \"notification\" as a child of \"container\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;leaf x{type string;} notification x;}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"x\" of data definition/RPC/action/notification statement. /bb:x");
+    assert_null(lys_parse_mem(ctx, "module cc {yang-version 1.1; namespace urn:cc;prefix cc;container c {leaf y {type string;} notification y;}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"y\" of data definition/RPC/action/notification statement. /cc:c/y");
+    assert_null(lys_parse_mem(ctx, "module dd {yang-version 1.1; namespace urn:dd;prefix dd;container c {notification z; notification z;}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"z\" of data definition/RPC/action/notification statement. /dd:c/z");
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule eesub {belongs-to ee {prefix ee;} rpc w;}");
+    assert_null(lys_parse_mem(ctx, "module ee {yang-version 1.1; namespace urn:ee;prefix ee;include eesub; notification w;}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"w\" of data definition/RPC/action/notification statement. /ee:w");
+
+    assert_null(lys_parse_mem(ctx, "module ff {yang-version 1.1; namespace urn:ff;prefix ff; rpc test {input {container a {leaf b {type string;}}}}"
+                              "augment /test/input/a {notification invalid {leaf x {type string;}}}}", LYS_IN_YANG));
+    logbuf_assert("Notification \"invalid\" is placed inside RPC/action. /ff:{augment='/test/input/a'}/invalid");
+
+    assert_null(lys_parse_mem(ctx, "module gg {yang-version 1.1; namespace urn:gg;prefix gg; notification test {container a {leaf b {type string;}}}"
+                              "augment /test/a {notification invalid {leaf x {type string;}}}}", LYS_IN_YANG));
+    logbuf_assert("Notification \"invalid\" is placed inside another notification. /gg:{augment='/test/a'}/invalid");
+
+    assert_null(lys_parse_mem(ctx, "module hh {yang-version 1.1; namespace urn:hh;prefix hh; rpc test {input {container a {uses grp;}}}"
+                              "grouping grp {notification invalid {leaf x {type string;}}}}", LYS_IN_YANG));
+    logbuf_assert("Notification \"invalid\" is placed inside RPC/action. /hh:test/input/a/{uses='grp'}/invalid");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+/**
+ * actually the same as length restriction (tested in test_type_length()), so just check the correct handling in appropriate types,
+ * do not test the expression itself
+ */
+static void
+test_type_range(void **state)
+{
+    *state = test_type_range;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_type *type;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;leaf l {type int8 {range min..10|max;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_INT8, type->basetype);
+    assert_non_null(((struct lysc_type_num*)type)->range);
+    assert_non_null(((struct lysc_type_num*)type)->range->parts);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+    assert_int_equal(-128, ((struct lysc_type_num*)type)->range->parts[0].min_64);
+    assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_64);
+    assert_int_equal(127, ((struct lysc_type_num*)type)->range->parts[1].min_64);
+    assert_int_equal(127, ((struct lysc_type_num*)type)->range->parts[1].max_64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;leaf l {type int16 {range min..10|max;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_INT16, type->basetype);
+    assert_non_null(((struct lysc_type_num*)type)->range);
+    assert_non_null(((struct lysc_type_num*)type)->range->parts);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+    assert_int_equal(-32768, ((struct lysc_type_num*)type)->range->parts[0].min_64);
+    assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_64);
+    assert_int_equal(32767, ((struct lysc_type_num*)type)->range->parts[1].min_64);
+    assert_int_equal(32767, ((struct lysc_type_num*)type)->range->parts[1].max_64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c;leaf l {type int32 {range min..10|max;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_INT32, type->basetype);
+    assert_non_null(((struct lysc_type_num*)type)->range);
+    assert_non_null(((struct lysc_type_num*)type)->range->parts);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+    assert_int_equal(INT64_C(-2147483648), ((struct lysc_type_num*)type)->range->parts[0].min_64);
+    assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_64);
+    assert_int_equal(INT64_C(2147483647), ((struct lysc_type_num*)type)->range->parts[1].min_64);
+    assert_int_equal(INT64_C(2147483647), ((struct lysc_type_num*)type)->range->parts[1].max_64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d;leaf l {type int64 {range min..10|max;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_INT64, type->basetype);
+    assert_non_null(((struct lysc_type_num*)type)->range);
+    assert_non_null(((struct lysc_type_num*)type)->range->parts);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+    assert_int_equal(INT64_C(-9223372036854775807) - INT64_C(1), ((struct lysc_type_num*)type)->range->parts[0].min_64);
+    assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_64);
+    assert_int_equal(INT64_C(9223372036854775807), ((struct lysc_type_num*)type)->range->parts[1].min_64);
+    assert_int_equal(INT64_C(9223372036854775807), ((struct lysc_type_num*)type)->range->parts[1].max_64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module e {namespace urn:e;prefix e;leaf l {type uint8 {range min..10|max;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_UINT8, type->basetype);
+    assert_non_null(((struct lysc_type_num*)type)->range);
+    assert_non_null(((struct lysc_type_num*)type)->range->parts);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+    assert_int_equal(0, ((struct lysc_type_num*)type)->range->parts[0].min_u64);
+    assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_u64);
+    assert_int_equal(255, ((struct lysc_type_num*)type)->range->parts[1].min_u64);
+    assert_int_equal(255, ((struct lysc_type_num*)type)->range->parts[1].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module f {namespace urn:f;prefix f;leaf l {type uint16 {range min..10|max;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_UINT16, type->basetype);
+    assert_non_null(((struct lysc_type_num*)type)->range);
+    assert_non_null(((struct lysc_type_num*)type)->range->parts);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+    assert_int_equal(0, ((struct lysc_type_num*)type)->range->parts[0].min_u64);
+    assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_u64);
+    assert_int_equal(65535, ((struct lysc_type_num*)type)->range->parts[1].min_u64);
+    assert_int_equal(65535, ((struct lysc_type_num*)type)->range->parts[1].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module g {namespace urn:g;prefix g;leaf l {type uint32 {range min..10|max;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_UINT32, type->basetype);
+    assert_non_null(((struct lysc_type_num*)type)->range);
+    assert_non_null(((struct lysc_type_num*)type)->range->parts);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+    assert_int_equal(0, ((struct lysc_type_num*)type)->range->parts[0].min_u64);
+    assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_u64);
+    assert_int_equal(UINT64_C(4294967295), ((struct lysc_type_num*)type)->range->parts[1].min_u64);
+    assert_int_equal(UINT64_C(4294967295), ((struct lysc_type_num*)type)->range->parts[1].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module h {namespace urn:h;prefix h;leaf l {type uint64 {range min..10|max;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_UINT64, type->basetype);
+    assert_non_null(((struct lysc_type_num*)type)->range);
+    assert_non_null(((struct lysc_type_num*)type)->range->parts);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+    assert_int_equal(0, ((struct lysc_type_num*)type)->range->parts[0].min_u64);
+    assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_u64);
+    assert_int_equal(UINT64_C(18446744073709551615), ((struct lysc_type_num*)type)->range->parts[1].min_u64);
+    assert_int_equal(UINT64_C(18446744073709551615), ((struct lysc_type_num*)type)->range->parts[1].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module i {namespace urn:i;prefix i;typedef mytype {type uint8 {range 10..100;}}"
+                                             "typedef mytype2 {type mytype;} leaf l {type mytype2;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(3, type->refcount);
+    assert_int_equal(LY_TYPE_UINT8, type->basetype);
+    assert_non_null(((struct lysc_type_num*)type)->range);
+    assert_non_null(((struct lysc_type_num*)type)->range->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module j {namespace urn:j;prefix j;"
+                                             "typedef mytype {type uint8 {range 1..100{description \"one to hundred\";reference A;}}}"
+                                             "leaf l {type mytype {range 1..10 {description \"one to ten\";reference B;}}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_UINT8, type->basetype);
+    assert_non_null(((struct lysc_type_num*)type)->range);
+    assert_string_equal("one to ten", ((struct lysc_type_num*)type)->range->dsc);
+    assert_string_equal("B", ((struct lysc_type_num*)type)->range->ref);
+    assert_non_null(((struct lysc_type_num*)type)->range->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_num*)type)->range->parts));
+    assert_int_equal(1, ((struct lysc_type_num*)type)->range->parts[0].min_u64);
+    assert_int_equal(10, ((struct lysc_type_num*)type)->range->parts[0].max_u64);
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_length(void **state)
+{
+    *state = test_type_length;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_type *type;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;leaf l {type binary {length min {error-app-tag errortag;error-message error;}}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_non_null(((struct lysc_type_bin*)type)->length);
+    assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+    assert_string_equal("errortag", ((struct lysc_type_bin*)type)->length->eapptag);
+    assert_string_equal("error", ((struct lysc_type_bin*)type)->length->emsg);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+    assert_int_equal(0, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+    assert_int_equal(0, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;leaf l {type binary {length max;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_non_null(((struct lysc_type_bin*)type)->length);
+    assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+    assert_int_equal(UINT64_C(18446744073709551615), ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+    assert_int_equal(UINT64_C(18446744073709551615), ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c;leaf l {type binary {length min..max;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_non_null(((struct lysc_type_bin*)type)->length);
+    assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+    assert_int_equal(0, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+    assert_int_equal(UINT64_C(18446744073709551615), ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d;leaf l {type binary {length 5;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_non_null(((struct lysc_type_bin*)type)->length);
+    assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+    assert_int_equal(5, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+    assert_int_equal(5, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module e {namespace urn:e;prefix e;leaf l {type binary {length 1..10;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_non_null(((struct lysc_type_bin*)type)->length);
+    assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+    assert_int_equal(1, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+    assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module f {namespace urn:f;prefix f;leaf l {type binary {length 1..10|20..30;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_non_null(((struct lysc_type_bin*)type)->length);
+    assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+    assert_int_equal(1, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+    assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+    assert_int_equal(20, ((struct lysc_type_bin*)type)->length->parts[1].min_u64);
+    assert_int_equal(30, ((struct lysc_type_bin*)type)->length->parts[1].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module g {namespace urn:g;prefix g;leaf l {type binary {length \"16 | 32\";}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_non_null(((struct lysc_type_bin*)type)->length);
+    assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+    assert_int_equal(16, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+    assert_int_equal(16, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+    assert_int_equal(32, ((struct lysc_type_bin*)type)->length->parts[1].min_u64);
+    assert_int_equal(32, ((struct lysc_type_bin*)type)->length->parts[1].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module h {namespace urn:h;prefix h;typedef mytype {type binary {length 10;}}"
+                                             "leaf l {type mytype {length \"10\";}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_non_null(((struct lysc_type_bin*)type)->length);
+    assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+    assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+    assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module i {namespace urn:i;prefix i;typedef mytype {type binary {length 10..100;}}"
+                                             "leaf l {type mytype {length \"50\";}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_non_null(((struct lysc_type_bin*)type)->length);
+    assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+    assert_int_equal(50, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+    assert_int_equal(50, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module j {namespace urn:j;prefix j;typedef mytype {type binary {length 10..100;}}"
+                                             "leaf l {type mytype {length \"10..30|60..100\";}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_non_null(((struct lysc_type_bin*)type)->length);
+    assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+    assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+    assert_int_equal(30, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+    assert_int_equal(60, ((struct lysc_type_bin*)type)->length->parts[1].min_u64);
+    assert_int_equal(100, ((struct lysc_type_bin*)type)->length->parts[1].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module k {namespace urn:k;prefix k;typedef mytype {type binary {length 10..100;}}"
+                                             "leaf l {type mytype {length \"10..80\";}}leaf ll {type mytype;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_non_null(((struct lysc_type_bin*)type)->length);
+    assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+    assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+    assert_int_equal(80, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+    type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+    assert_non_null(type);
+    assert_int_equal(2, type->refcount);
+    assert_non_null(((struct lysc_type_bin*)type)->length);
+    assert_non_null(((struct lysc_type_bin*)type)->length->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_bin*)type)->length->parts));
+    assert_int_equal(10, ((struct lysc_type_bin*)type)->length->parts[0].min_u64);
+    assert_int_equal(100, ((struct lysc_type_bin*)type)->length->parts[0].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module l {namespace urn:l;prefix l;typedef mytype {type string {length 10..100;}}"
+                                             "typedef mytype2 {type mytype {pattern '[0-9]*';}} leaf l {type mytype2 {pattern '[0-4]*';}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_STRING, type->basetype);
+    assert_int_equal(1, type->refcount);
+    assert_non_null(((struct lysc_type_str*)type)->length);
+    assert_non_null(((struct lysc_type_str*)type)->length->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->length->parts));
+    assert_int_equal(10, ((struct lysc_type_str*)type)->length->parts[0].min_u64);
+    assert_int_equal(100, ((struct lysc_type_str*)type)->length->parts[0].max_u64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module m {namespace urn:m;prefix m;typedef mytype {type string {length 10;}}"
+                                             "leaf l {type mytype {length min..max;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_STRING, type->basetype);
+    assert_int_equal(1, type->refcount);
+    assert_non_null(((struct lysc_type_str*)type)->length);
+    assert_non_null(((struct lysc_type_str*)type)->length->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->length->parts));
+    assert_int_equal(10, ((struct lysc_type_str*)type)->length->parts[0].min_u64);
+    assert_int_equal(10, ((struct lysc_type_str*)type)->length->parts[0].max_u64);
+
+    /* invalid values */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;leaf l {type binary {length -10;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - value \"-10\" does not fit the type limitations. /aa:l");
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;leaf l {type binary {length 18446744073709551616;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - invalid value \"18446744073709551616\". /bb:l");
+    assert_null(lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;leaf l {type binary {length \"max .. 10\";}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - unexpected data after max keyword (.. 10). /cc:l");
+    assert_null(lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;leaf l {type binary {length 50..10;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - values are not in ascending order (10). /dd:l");
+    assert_null(lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;leaf l {type binary {length \"50 | 10\";}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - values are not in ascending order (10). /ee:l");
+    assert_null(lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;leaf l {type binary {length \"x\";}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - unexpected data (x). /ff:l");
+    assert_null(lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;leaf l {type binary {length \"50 | min\";}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - unexpected data before min keyword (50 | ). /gg:l");
+    assert_null(lys_parse_mem(ctx, "module hh {namespace urn:hh;prefix hh;leaf l {type binary {length \"| 50\";}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - unexpected beginning of the expression (| 50). /hh:l");
+    assert_null(lys_parse_mem(ctx, "module ii {namespace urn:ii;prefix ii;leaf l {type binary {length \"10 ..\";}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - unexpected end of the expression after \"..\" (10 ..). /ii:l");
+    assert_null(lys_parse_mem(ctx, "module jj {namespace urn:jj;prefix jj;leaf l {type binary {length \".. 10\";}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - unexpected \"..\" without a lower bound. /jj:l");
+    assert_null(lys_parse_mem(ctx, "module kk {namespace urn:kk;prefix kk;leaf l {type binary {length \"10 |\";}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - unexpected end of the expression (10 |). /kk:l");
+    assert_null(lys_parse_mem(ctx, "module kl {namespace urn:kl;prefix kl;leaf l {type binary {length \"10..20 | 15..30\";}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - values are not in ascending order (15). /kl:l");
+
+    assert_null(lys_parse_mem(ctx, "module ll {namespace urn:ll;prefix ll;typedef mytype {type binary {length 10;}}"
+                                   "leaf l {type mytype {length 11;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - the derived restriction (11) is not equally or more limiting. /ll:l");
+    assert_null(lys_parse_mem(ctx, "module mm {namespace urn:mm;prefix mm;typedef mytype {type binary {length 10..100;}}"
+                                   "leaf l {type mytype {length 1..11;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - the derived restriction (1..11) is not equally or more limiting. /mm:l");
+    assert_null(lys_parse_mem(ctx, "module nn {namespace urn:nn;prefix nn;typedef mytype {type binary {length 10..100;}}"
+                                   "leaf l {type mytype {length 20..110;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - the derived restriction (20..110) is not equally or more limiting. /nn:l");
+    assert_null(lys_parse_mem(ctx, "module oo {namespace urn:oo;prefix oo;typedef mytype {type binary {length 10..100;}}"
+                                   "leaf l {type mytype {length 20..30|110..120;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - the derived restriction (20..30|110..120) is not equally or more limiting. /oo:l");
+    assert_null(lys_parse_mem(ctx, "module pp {namespace urn:pp;prefix pp;typedef mytype {type binary {length 10..11;}}"
+                                             "leaf l {type mytype {length 15;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - the derived restriction (15) is not equally or more limiting. /pp:l");
+    assert_null(lys_parse_mem(ctx, "module qq {namespace urn:qq;prefix qq;typedef mytype {type binary {length 10..20|30..40;}}"
+                                             "leaf l {type mytype {length 15..35;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - the derived restriction (15..35) is not equally or more limiting. /qq:l");
+    assert_null(lys_parse_mem(ctx, "module rr {namespace urn:rr;prefix rr;typedef mytype {type binary {length 10;}}"
+                                             "leaf l {type mytype {length 10..35;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid length restriction - the derived restriction (10..35) is not equally or more limiting. /rr:l");
+
+    assert_null(lys_parse_mem(ctx, "module ss {namespace urn:ss;prefix ss;leaf l {type binary {pattern '[0-9]*';}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid type restrictions for binary type. /ss:l");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_pattern(void **state)
+{
+    *state = test_type_pattern;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_type *type;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1; namespace urn:a;prefix a;leaf l {type string {"
+                                        "pattern .* {error-app-tag errortag;error-message error;}"
+                                        "pattern [0-9].*[0-9] {modifier invert-match;}}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_non_null(((struct lysc_type_str*)type)->patterns);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->patterns));
+    assert_string_equal("errortag", ((struct lysc_type_str*)type)->patterns[0]->eapptag);
+    assert_string_equal("error", ((struct lysc_type_str*)type)->patterns[0]->emsg);
+    assert_string_equal(".*", ((struct lysc_type_str*)type)->patterns[0]->expr);
+    assert_int_equal(0, ((struct lysc_type_str*)type)->patterns[0]->inverted);
+    assert_null(((struct lysc_type_str*)type)->patterns[1]->eapptag);
+    assert_null(((struct lysc_type_str*)type)->patterns[1]->emsg);
+    assert_string_equal("[0-9].*[0-9]", ((struct lysc_type_str*)type)->patterns[1]->expr);
+    assert_int_equal(1, ((struct lysc_type_str*)type)->patterns[1]->inverted);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;typedef mytype {type string {pattern '[0-9]*';}}"
+                                             "typedef mytype2 {type mytype {length 10;}} leaf l {type mytype2 {pattern '[0-4]*';}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_STRING, type->basetype);
+    assert_int_equal(1, type->refcount);
+    assert_non_null(((struct lysc_type_str*)type)->patterns);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->patterns));
+    assert_string_equal("[0-9]*", ((struct lysc_type_str*)type)->patterns[0]->expr);
+    assert_int_equal(3, ((struct lysc_type_str*)type)->patterns[0]->refcount);
+    assert_string_equal("[0-4]*", ((struct lysc_type_str*)type)->patterns[1]->expr);
+    assert_int_equal(1, ((struct lysc_type_str*)type)->patterns[1]->refcount);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c;typedef mytype {type string {pattern '[0-9]*';}}"
+                                             "leaf l {type mytype {length 10;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_STRING, type->basetype);
+    assert_int_equal(1, type->refcount);
+    assert_non_null(((struct lysc_type_str*)type)->patterns);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->patterns));
+    assert_string_equal("[0-9]*", ((struct lysc_type_str*)type)->patterns[0]->expr);
+    assert_int_equal(2, ((struct lysc_type_str*)type)->patterns[0]->refcount);
+
+    /* test substitutions */
+    assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d;leaf l {type string {"
+                                        "pattern '^\\p{IsLatinExtended-A}$';}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_non_null(((struct lysc_type_str*)type)->patterns);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_str*)type)->patterns));
+    assert_string_equal("^\\p{IsLatinExtended-A}$", ((struct lysc_type_str*)type)->patterns[0]->expr);
+    /* TODO check some data "^Å™$" */
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_enum(void **state)
+{
+    *state = test_type_enum;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_type *type;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1; namespace urn:a;prefix a;feature f; leaf l {type enumeration {"
+                                        "enum automin; enum min {value -2147483648;}enum one {if-feature f; value 1;}"
+                                        "enum two; enum seven {value 7;}enum eight;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_ENUM, type->basetype);
+    assert_non_null(((struct lysc_type_enum*)type)->enums);
+    assert_int_equal(6, LY_ARRAY_SIZE(((struct lysc_type_enum*)type)->enums));
+    assert_non_null(((struct lysc_type_enum*)type)->enums[2].iffeatures);
+    assert_string_equal("automin", ((struct lysc_type_enum*)type)->enums[0].name);
+    assert_int_equal(0, ((struct lysc_type_enum*)type)->enums[0].value);
+    assert_string_equal("min", ((struct lysc_type_enum*)type)->enums[1].name);
+    assert_int_equal(-2147483648, ((struct lysc_type_enum*)type)->enums[1].value);
+    assert_string_equal("one", ((struct lysc_type_enum*)type)->enums[2].name);
+    assert_int_equal(1, ((struct lysc_type_enum*)type)->enums[2].value);
+    assert_string_equal("two", ((struct lysc_type_enum*)type)->enums[3].name);
+    assert_int_equal(2, ((struct lysc_type_enum*)type)->enums[3].value);
+    assert_string_equal("seven", ((struct lysc_type_enum*)type)->enums[4].name);
+    assert_int_equal(7, ((struct lysc_type_enum*)type)->enums[4].value);
+    assert_string_equal("eight", ((struct lysc_type_enum*)type)->enums[5].name);
+    assert_int_equal(8, ((struct lysc_type_enum*)type)->enums[5].value);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1; namespace urn:b;prefix b;feature f; typedef mytype {type enumeration {"
+                                        "enum 11; enum min {value -2147483648;}enum x$&;"
+                                        "enum two; enum seven {value 7;}enum eight;}} leaf l { type mytype {enum seven;enum eight;}}}",
+                                        LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_ENUM, type->basetype);
+    assert_non_null(((struct lysc_type_enum*)type)->enums);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_enum*)type)->enums));
+    assert_string_equal("seven", ((struct lysc_type_enum*)type)->enums[0].name);
+    assert_int_equal(7, ((struct lysc_type_enum*)type)->enums[0].value);
+    assert_string_equal("eight", ((struct lysc_type_enum*)type)->enums[1].name);
+    assert_int_equal(8, ((struct lysc_type_enum*)type)->enums[1].value);
+
+
+    /* invalid cases */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; feature f; leaf l {type enumeration {"
+                                   "enum one {if-feature f;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid keyword \"if-feature\" as a child of \"enum\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                   "enum one {value -2147483649;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid value \"-2147483649\" of \"value\". Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                   "enum one {value 2147483648;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid value \"2147483648\" of \"value\". Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                   "enum one; enum one;}}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"one\" of enum statement. Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                   "enum '';}}}", LYS_IN_YANG));
+    logbuf_assert("Enum name must not be zero-length. Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                   "enum ' x';}}}", LYS_IN_YANG));
+    logbuf_assert("Enum name must not have any leading or trailing whitespaces (\" x\"). Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                   "enum 'x ';}}}", LYS_IN_YANG));
+    logbuf_assert("Enum name must not have any leading or trailing whitespaces (\"x \"). Line number 1.");
+    assert_non_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                  "enum 'inva\nlid';}}}", LYS_IN_YANG));
+    logbuf_assert("Control characters in enum name should be avoided (\"inva\nlid\", character number 5).");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; leaf l {type enumeration;}}", LYS_IN_YANG));
+    logbuf_assert("Missing enum substatement for enumeration type. /bb:l");
+
+    assert_null(lys_parse_mem(ctx, "module cc {yang-version 1.1;namespace urn:cc;prefix cc;typedef mytype {type enumeration {enum one;}}"
+                                             "leaf l {type mytype {enum two;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid enumeration - derived type adds new item \"two\". /cc:l");
+
+    assert_null(lys_parse_mem(ctx, "module dd {yang-version 1.1;namespace urn:dd;prefix dd;typedef mytype {type enumeration {enum one;}}"
+                                             "leaf l {type mytype {enum one {value 1;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid enumeration - value of the item \"one\" has changed from 0 to 1 in the derived type. /dd:l");
+    assert_null(lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;leaf l {type enumeration {enum x {value 2147483647;}enum y;}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid enumeration - it is not possible to auto-assign enum value for \"y\" since the highest value is already 2147483647. /ee:l");
+
+    assert_null(lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;leaf l {type enumeration {enum x {value 1;}enum y {value 1;}}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid enumeration - value 1 collide in items \"y\" and \"x\". /ff:l");
+
+    assert_null(lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;typedef mytype {type enumeration;}"
+                                             "leaf l {type mytype {enum one;}}}", LYS_IN_YANG));
+    logbuf_assert("Missing enum substatement for enumeration type mytype. /gg:l");
+
+    assert_null(lys_parse_mem(ctx, "module hh {namespace urn:hh;prefix hh; typedef mytype {type enumeration {enum one;}}"
+                                        "leaf l {type mytype {enum one;}}}", LYS_IN_YANG));
+    logbuf_assert("Enumeration type can be subtyped only in YANG 1.1 modules. /hh:l");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_bits(void **state)
+{
+    *state = test_type_bits;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_type *type;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1; namespace urn:a;prefix a;feature f; leaf l {type bits {"
+                                        "bit automin; bit one {if-feature f; position 1;}"
+                                        "bit two; bit seven {position 7;}bit eight;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_BITS, type->basetype);
+    assert_non_null(((struct lysc_type_bits*)type)->bits);
+    assert_int_equal(5, LY_ARRAY_SIZE(((struct lysc_type_bits*)type)->bits));
+    assert_non_null(((struct lysc_type_bits*)type)->bits[1].iffeatures);
+    assert_string_equal("automin", ((struct lysc_type_bits*)type)->bits[0].name);
+    assert_int_equal(0, ((struct lysc_type_bits*)type)->bits[0].position);
+    assert_string_equal("one", ((struct lysc_type_bits*)type)->bits[1].name);
+    assert_int_equal(1, ((struct lysc_type_bits*)type)->bits[1].position);
+    assert_string_equal("two", ((struct lysc_type_bits*)type)->bits[2].name);
+    assert_int_equal(2, ((struct lysc_type_bits*)type)->bits[2].position);
+    assert_string_equal("seven", ((struct lysc_type_bits*)type)->bits[3].name);
+    assert_int_equal(7, ((struct lysc_type_bits*)type)->bits[3].position);
+    assert_string_equal("eight", ((struct lysc_type_bits*)type)->bits[4].name);
+    assert_int_equal(8, ((struct lysc_type_bits*)type)->bits[4].position);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1;namespace urn:b;prefix b;feature f; typedef mytype {type bits {"
+                                        "bit automin; bit one;bit two; bit seven {position 7;}bit eight;}} leaf l { type mytype {bit eight;bit seven;bit automin;}}}",
+                                        LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_BITS, type->basetype);
+    assert_non_null(((struct lysc_type_bits*)type)->bits);
+    assert_int_equal(3, LY_ARRAY_SIZE(((struct lysc_type_bits*)type)->bits));
+    assert_string_equal("automin", ((struct lysc_type_bits*)type)->bits[0].name);
+    assert_int_equal(0, ((struct lysc_type_bits*)type)->bits[0].position);
+    assert_string_equal("seven", ((struct lysc_type_bits*)type)->bits[1].name);
+    assert_int_equal(7, ((struct lysc_type_bits*)type)->bits[1].position);
+    assert_string_equal("eight", ((struct lysc_type_bits*)type)->bits[2].name);
+    assert_int_equal(8, ((struct lysc_type_bits*)type)->bits[2].position);
+
+
+    /* invalid cases */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; feature f; leaf l {type bits {"
+                                   "bit one {if-feature f;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid keyword \"if-feature\" as a child of \"bit\" - the statement is allowed only in YANG 1.1 modules. Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+                                   "bit one {position -1;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid value \"-1\" of \"position\". Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+                                   "bit one {position 4294967296;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid value \"4294967296\" of \"position\". Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+                                   "bit one; bit one;}}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"one\" of bit statement. Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+                                   "bit '11';}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid identifier first character '1'. Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+                                   "bit 'x1$1';}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid identifier character '$'. Line number 1.");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; leaf l {type bits;}}", LYS_IN_YANG));
+    logbuf_assert("Missing bit substatement for bits type. /bb:l");
+
+    assert_null(lys_parse_mem(ctx, "module cc {yang-version 1.1;namespace urn:cc;prefix cc;typedef mytype {type bits {bit one;}}"
+                                             "leaf l {type mytype {bit two;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid bits - derived type adds new item \"two\". /cc:l");
+
+    assert_null(lys_parse_mem(ctx, "module dd {yang-version 1.1;namespace urn:dd;prefix dd;typedef mytype {type bits {bit one;}}"
+                                             "leaf l {type mytype {bit one {position 1;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid bits - position of the item \"one\" has changed from 0 to 1 in the derived type. /dd:l");
+    assert_null(lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;leaf l {type bits {bit x {position 4294967295;}bit y;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid bits - it is not possible to auto-assign bit position for \"y\" since the highest value is already 4294967295. /ee:l");
+
+    assert_null(lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;leaf l {type bits {bit x {position 1;}bit y {position 1;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid bits - position 1 collide in items \"y\" and \"x\". /ff:l");
+
+    assert_null(lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;typedef mytype {type bits;}"
+                                             "leaf l {type mytype {bit one;}}}", LYS_IN_YANG));
+    logbuf_assert("Missing bit substatement for bits type mytype. /gg:l");
+
+    assert_null(lys_parse_mem(ctx, "module hh {namespace urn:hh;prefix hh; typedef mytype {type bits {bit one;}}"
+                                        "leaf l {type mytype {bit one;}}}", LYS_IN_YANG));
+    logbuf_assert("Bits type can be subtyped only in YANG 1.1 modules. /hh:l");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_dec64(void **state)
+{
+    *state = test_type_dec64;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_type *type;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;leaf l {type decimal64 {"
+                                        "fraction-digits 2;range min..max;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_DEC64, type->basetype);
+    assert_int_equal(2, ((struct lysc_type_dec*)type)->fraction_digits);
+    assert_non_null(((struct lysc_type_dec*)type)->range);
+    assert_non_null(((struct lysc_type_dec*)type)->range->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_dec*)type)->range->parts));
+    assert_int_equal(INT64_C(-9223372036854775807) - INT64_C(1), ((struct lysc_type_dec*)type)->range->parts[0].min_64);
+    assert_int_equal(INT64_C(9223372036854775807), ((struct lysc_type_dec*)type)->range->parts[0].max_64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;typedef mytype {type decimal64 {"
+                                        "fraction-digits 2;range '3.14 | 5.1 | 10';}}leaf l {type mytype;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_DEC64, type->basetype);
+    assert_int_equal(2, ((struct lysc_type_dec*)type)->fraction_digits);
+    assert_non_null(((struct lysc_type_dec*)type)->range);
+    assert_non_null(((struct lysc_type_dec*)type)->range->parts);
+    assert_int_equal(3, LY_ARRAY_SIZE(((struct lysc_type_dec*)type)->range->parts));
+    assert_int_equal(314, ((struct lysc_type_dec*)type)->range->parts[0].min_64);
+    assert_int_equal(314, ((struct lysc_type_dec*)type)->range->parts[0].max_64);
+    assert_int_equal(510, ((struct lysc_type_dec*)type)->range->parts[1].min_64);
+    assert_int_equal(510, ((struct lysc_type_dec*)type)->range->parts[1].max_64);
+    assert_int_equal(1000, ((struct lysc_type_dec*)type)->range->parts[2].min_64);
+    assert_int_equal(1000, ((struct lysc_type_dec*)type)->range->parts[2].max_64);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c;typedef mytype {type decimal64 {"
+                                        "fraction-digits 2;range '1 .. 65535';}}leaf l {type mytype;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_int_equal(LY_TYPE_DEC64, type->basetype);
+    assert_int_equal(2, ((struct lysc_type_dec*)type)->fraction_digits);
+    assert_non_null(((struct lysc_type_dec*)type)->range);
+    assert_non_null(((struct lysc_type_dec*)type)->range->parts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_dec*)type)->range->parts));
+    assert_int_equal(100, ((struct lysc_type_dec*)type)->range->parts[0].min_64);
+    assert_int_equal(6553500, ((struct lysc_type_dec*)type)->range->parts[0].max_64);
+
+    /* invalid cases */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type decimal64 {fraction-digits 0;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid value \"0\" of \"fraction-digits\". Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type decimal64 {fraction-digits -1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid value \"-1\" of \"fraction-digits\". Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type decimal64 {fraction-digits 19;}}}", LYS_IN_YANG));
+    logbuf_assert("Value \"19\" is out of \"fraction-digits\" bounds. Line number 1.");
+
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type decimal64;}}", LYS_IN_YANG));
+    logbuf_assert("Missing fraction-digits substatement for decimal64 type. /aa:l");
+
+    assert_null(lys_parse_mem(ctx, "module ab {namespace urn:ab;prefix ab; typedef mytype {type decimal64;}leaf l {type mytype;}}", LYS_IN_YANG));
+    logbuf_assert("Missing fraction-digits substatement for decimal64 type mytype. /ab:l");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; leaf l {type decimal64 {fraction-digits 2;"
+                                        "range '3.142';}}}", LYS_IN_YANG));
+    logbuf_assert("Range boundary \"3.142\" of decimal64 type exceeds defined number (2) of fraction digits. /bb:l");
+
+    assert_null(lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc; leaf l {type decimal64 {fraction-digits 2;"
+                                        "range '4 | 3.14';}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid range restriction - values are not in ascending order (3.14). /cc:l");
+
+    assert_null(lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd; typedef mytype {type decimal64 {fraction-digits 2;}}"
+                                        "leaf l {type mytype {fraction-digits 3;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid fraction-digits substatement for type not directly derived from decimal64 built-in type. /dd:l");
+
+    assert_null(lys_parse_mem(ctx, "module de {namespace urn:de;prefix de; typedef mytype {type decimal64 {fraction-digits 2;}}"
+                                        "typedef mytype2 {type mytype {fraction-digits 3;}}leaf l {type mytype2;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid fraction-digits substatement for type \"mytype2\" not directly derived from decimal64 built-in type. /de:l");
+
+    assert_null(lys_parse_mem(ctx, "module ee {namespace urn:c;prefix c;typedef mytype {type decimal64 {"
+                              "fraction-digits 18;range '-10 .. 0';}}leaf l {type mytype;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid range restriction - invalid value \"-10000000000000000000\". /ee:l");
+    assert_null(lys_parse_mem(ctx, "module ee {namespace urn:c;prefix c;typedef mytype {type decimal64 {"
+                              "fraction-digits 18;range '0 .. 10';}}leaf l {type mytype;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid range restriction - invalid value \"10000000000000000000\". /ee:l");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_instanceid(void **state)
+{
+    *state = test_type_instanceid;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_type *type;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;typedef mytype {type instance-identifier {require-instance false;}}"
+                                        "leaf l1 {type instance-identifier {require-instance true;}}"
+                                        "leaf l2 {type mytype;} leaf l3 {type instance-identifier;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_INST, type->basetype);
+    assert_int_equal(1, ((struct lysc_type_instanceid*)type)->require_instance);
+
+    type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_INST, type->basetype);
+    assert_int_equal(0, ((struct lysc_type_instanceid*)type)->require_instance);
+
+    type = ((struct lysc_node_leaf*)mod->compiled->data->next->next)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_INST, type->basetype);
+    assert_int_equal(1, ((struct lysc_type_instanceid*)type)->require_instance);
+
+    /* invalid cases */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {require-instance yes;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid value \"yes\" of \"require-instance\". Line number 1.");
+
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type instance-identifier {fraction-digits 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid type restrictions for instance-identifier type. /aa:l");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_identityref(void **state)
+{
+    *state = test_type_identityref;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_type *type;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1;namespace urn:a;prefix a;identity i; identity j; identity k {base i;}"
+                                        "typedef mytype {type identityref {base i;}}"
+                                        "leaf l1 {type mytype;} leaf l2 {type identityref {base a:k; base j;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_IDENT, type->basetype);
+    assert_non_null(((struct lysc_type_identityref*)type)->bases);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_type_identityref*)type)->bases));
+    assert_string_equal("i", ((struct lysc_type_identityref*)type)->bases[0]->name);
+
+    type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_IDENT, type->basetype);
+    assert_non_null(((struct lysc_type_identityref*)type)->bases);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_identityref*)type)->bases));
+    assert_string_equal("k", ((struct lysc_type_identityref*)type)->bases[0]->name);
+    assert_string_equal("j", ((struct lysc_type_identityref*)type)->bases[1]->name);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1;namespace urn:b;prefix b;import a {prefix a;}"
+                                        "leaf l {type identityref {base a:k; base a:j;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_IDENT, type->basetype);
+    assert_non_null(((struct lysc_type_identityref*)type)->bases);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_identityref*)type)->bases));
+    assert_string_equal("k", ((struct lysc_type_identityref*)type)->bases[0]->name);
+    assert_string_equal("j", ((struct lysc_type_identityref*)type)->bases[1]->name);
+
+    /* invalid cases */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type identityref;}}", LYS_IN_YANG));
+    logbuf_assert("Missing base substatement for identityref type. /aa:l");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; typedef mytype {type identityref;}"
+                                        "leaf l {type mytype;}}", LYS_IN_YANG));
+    logbuf_assert("Missing base substatement for identityref type mytype. /bb:l");
+
+    assert_null(lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc; identity i; typedef mytype {type identityref {base i;}}"
+                                        "leaf l {type mytype {base i;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid base substatement for the type not directly derived from identityref built-in type. /cc:l");
+
+    assert_null(lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd; identity i; typedef mytype {type identityref {base i;}}"
+                                        "typedef mytype2 {type mytype {base i;}}leaf l {type mytype2;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid base substatement for the type \"mytype2\" not directly derived from identityref built-in type. /dd:l");
+
+    assert_null(lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee; identity i; identity j;"
+                                        "leaf l {type identityref {base i;base j;}}}", LYS_IN_YANG));
+    logbuf_assert("Multiple bases in identityref type are allowed only in YANG 1.1 modules. /ee:l");
+
+    assert_null(lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff; identity i;leaf l {type identityref {base j;}}}", LYS_IN_YANG));
+    logbuf_assert("Unable to find base (j) of identityref. /ff:l");
+
+    assert_null(lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;leaf l {type identityref {base x:j;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid prefix used for base (x:j) of identityref. /gg:l");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_leafref(void **state)
+{
+    *state = test_type_leafref;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_type *type;
+    const char *path, *name, *prefix;
+    size_t prefix_len, name_len;
+    int parent_times, has_predicate;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    /* lys_path_token() */
+    path = "invalid_path";
+    parent_times = 0;
+    assert_int_equal(LY_EINVAL, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+    path = "..";
+    parent_times = 0;
+    assert_int_equal(LY_EINVAL, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+    path = "..[";
+    parent_times = 0;
+    assert_int_equal(LY_EINVAL, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+    path = "../";
+    parent_times = 0;
+    assert_int_equal(LY_EINVAL, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+    path = "/";
+    parent_times = 0;
+    assert_int_equal(LY_EINVAL, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+
+    path = "../../pref:id/xxx[predicate]/invalid!!!";
+    parent_times = 0;
+    assert_int_equal(LY_SUCCESS, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+    assert_string_equal("/xxx[predicate]/invalid!!!", path);
+    assert_int_equal(4, prefix_len);
+    assert_int_equal(0, strncmp("pref", prefix, prefix_len));
+    assert_int_equal(2, name_len);
+    assert_int_equal(0, strncmp("id", name, name_len));
+    assert_int_equal(2, parent_times);
+    assert_int_equal(0, has_predicate);
+    assert_int_equal(LY_SUCCESS, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+    assert_string_equal("[predicate]/invalid!!!", path);
+    assert_int_equal(0, prefix_len);
+    assert_null(prefix);
+    assert_int_equal(3, name_len);
+    assert_int_equal(0, strncmp("xxx", name, name_len));
+    assert_int_equal(1, has_predicate);
+    path += 11;
+    assert_int_equal(LY_EINVAL, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+    assert_string_equal("!!!", path);
+    assert_int_equal(0, prefix_len);
+    assert_null(prefix);
+    assert_int_equal(7, name_len);
+    assert_int_equal(0, strncmp("invalid", name, name_len));
+
+    path = "/absolute/prefix:path";
+    parent_times = 0;
+    assert_int_equal(LY_SUCCESS, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+    assert_string_equal("/prefix:path", path);
+    assert_int_equal(0, prefix_len);
+    assert_null(prefix);
+    assert_int_equal(8, name_len);
+    assert_int_equal(0, strncmp("absolute", name, name_len));
+    assert_int_equal(-1, parent_times);
+    assert_int_equal(0, has_predicate);
+    assert_int_equal(LY_SUCCESS, lys_path_token(&path, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate));
+    assert_int_equal(0, *path);
+    assert_int_equal(6, prefix_len);
+    assert_int_equal(0, strncmp("prefix", prefix, prefix_len));
+    assert_int_equal(4, name_len);
+    assert_int_equal(0, strncmp("path", name, name_len));
+    assert_int_equal(0, has_predicate);
+
+    /* complete leafref paths */
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1;namespace urn:a;prefix a;"
+                                        "leaf ref1 {type leafref {path /a:target1;}} leaf ref2 {type leafref {path /a/target2; require-instance false;}}"
+                                        "leaf target1 {type string;}container a {leaf target2 {type uint8;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_string_equal("/a:target1", ((struct lysc_type_leafref*)type)->path);
+    assert_ptr_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+    assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+    assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_leafref*)type)->realtype->basetype);
+    assert_int_equal(1, ((struct lysc_type_leafref*)type)->require_instance);
+    type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_string_equal("/a/target2", ((struct lysc_type_leafref*)type)->path);
+    assert_ptr_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+    assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+    assert_int_equal(LY_TYPE_UINT8, ((struct lysc_type_leafref*)type)->realtype->basetype);
+    assert_int_equal(0, ((struct lysc_type_leafref*)type)->require_instance);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b; typedef mytype {type leafref {path /b:target;}}"
+                                        "typedef mytype2 {type mytype;} typedef mytype3 {type leafref {path /target;}} leaf ref {type mytype2;}"
+                                        "leaf target {type leafref {path ../realtarget;}} leaf realtarget {type string;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_string_equal("/b:target", ((struct lysc_type_leafref* )type)->path);
+    assert_ptr_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+    assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+    assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_leafref*)type)->realtype->basetype);
+    assert_int_equal(1, ((struct lysc_type_leafref* )type)->require_instance);
+
+    /* prefixes are reversed to check using correct context of the path! */
+    assert_non_null(mod = lys_parse_mem(ctx, "module c {yang-version 1.1;namespace urn:c;prefix b; import b {prefix c;}"
+                                        "typedef mytype3 {type c:mytype {require-instance false;}}"
+                                        "leaf ref1 {type b:mytype3;}leaf ref2 {type c:mytype2;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_string_equal("/b:target", ((struct lysc_type_leafref* )type)->path);
+    assert_ptr_not_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+    assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+    assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_leafref*)type)->realtype->basetype);
+    assert_int_equal(0, ((struct lysc_type_leafref* )type)->require_instance);
+    type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_string_equal("/b:target", ((struct lysc_type_leafref* )type)->path);
+    assert_ptr_not_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+    assert_int_equal(1, ((struct lysc_type_leafref* )type)->require_instance);
+
+    /* non-prefixed nodes in path are supposed to be from the module where the leafref type is instantiated */
+    assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d; import b {prefix b;}"
+                                        "leaf ref {type b:mytype3;}leaf target {type int8;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_string_equal("/target", ((struct lysc_type_leafref* )type)->path);
+    assert_ptr_not_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+    assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+    assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_leafref*)type)->realtype->basetype);
+    assert_int_equal(1, ((struct lysc_type_leafref* )type)->require_instance);
+
+    /* conditional leafrefs */
+    assert_non_null(mod = lys_parse_mem(ctx, "module e {yang-version 1.1;namespace urn:e;prefix e;feature f1; feature f2;"
+                                        "leaf ref1 {if-feature 'f1 and f2';type leafref {path /target;}}"
+                                        "leaf target {if-feature f1; type boolean;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_string_equal("/target", ((struct lysc_type_leafref* )type)->path);
+    assert_ptr_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+    assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+    assert_int_equal(LY_TYPE_BOOL, ((struct lysc_type_leafref*)type)->realtype->basetype);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module f {namespace urn:f;prefix f;"
+                                        "list interface{key name;leaf name{type string;}list address {key ip;leaf ip {type string;}}}"
+                                        "container default-address{leaf ifname{type leafref{ path \"../../interface/name\";}}"
+                                          "leaf address {type leafref{ path \"../../interface[  name = current()/../ifname ]/address/ip\";}}}}",
+                                        LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)(*lysc_node_children_p(mod->compiled->data->prev, 0))->prev)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_string_equal("../../interface[  name = current()/../ifname ]/address/ip", ((struct lysc_type_leafref* )type)->path);
+    assert_ptr_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+    assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+    assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_leafref*)type)->realtype->basetype);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module g {namespace urn:g;prefix g;"
+                                        "leaf source {type leafref {path \"/endpoint-parent[id=current()/../field]/endpoint/name\";}}"
+                                        "leaf field {type int32;}list endpoint-parent {key id;leaf id {type int32;}"
+                                        "list endpoint {key name;leaf name {type string;}}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_string_equal("/endpoint-parent[id=current()/../field]/endpoint/name", ((struct lysc_type_leafref* )type)->path);
+    assert_ptr_equal(mod, ((struct lysc_type_leafref*)type)->path_context);
+    assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+    assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_leafref*)type)->realtype->basetype);
+
+    /* leafref to imported (not yet implemented) module */
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module h {namespace urn:h;prefix h; leaf h  {type uint16;}}");
+    assert_non_null(mod = lys_parse_mem(ctx, "module i {namespace urn:i;prefix i;import h {prefix h;}"
+                                        "leaf i {type leafref {path /h:h;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+    assert_int_equal(LY_TYPE_UINT16, ((struct lysc_type_leafref*)type)->realtype->basetype);
+    assert_non_null(mod = ly_ctx_get_module_implemented(ctx, "h"));
+    assert_int_equal(1, mod->implemented);
+    assert_non_null(mod->compiled->data);
+    assert_string_equal("h", mod->compiled->data->name);
+
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module j {namespace urn:j;prefix j; leaf j  {type string;}}");
+    assert_non_null(mod = lys_parse_mem(ctx, "module k {namespace urn:k;prefix k;import j {prefix j;}"
+                                        "leaf i {type leafref {path \"/ilist[name = current()/../j:j]/value\";}}"
+                                        "list ilist {key name; leaf name {type string;} leaf value {type uint16;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+    assert_int_equal(LY_TYPE_UINT16, ((struct lysc_type_leafref*)type)->realtype->basetype);
+    assert_non_null(mod = ly_ctx_get_module_implemented(ctx, "j"));
+    assert_int_equal(1, mod->implemented);
+    assert_non_null(mod->compiled->data);
+    assert_string_equal("j", mod->compiled->data->name);
+
+    /* leafref with a default value */
+    assert_non_null(mod = lys_parse_mem(ctx, "module l {namespace urn:l;prefix l;"
+                                        "leaf source {type leafref {path \"../target\";}default true;}"
+                                        "leaf target {type boolean;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_LEAFREF, type->basetype);
+    assert_string_equal("../target", ((struct lysc_type_leafref* )type)->path);
+    assert_non_null(((struct lysc_type_leafref*)type)->realtype);
+    assert_int_equal(LY_TYPE_BOOL, ((struct lysc_type_leafref*)type)->realtype->basetype);
+    assert_non_null(((struct lysc_node_leaf*)mod->compiled->data)->dflt);
+    assert_int_equal(LY_TYPE_BOOL, ((struct lysc_node_leaf*)mod->compiled->data)->dflt->realtype->basetype);
+    assert_int_equal(1, ((struct lysc_node_leaf*)mod->compiled->data)->dflt->boolean);
+
+    /* invalid paths */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;container a {leaf target2 {type uint8;}}"
+                                        "leaf ref1 {type leafref {path ../a/invalid;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path - unable to find \"../a/invalid\". /aa:ref1");
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;container a {leaf target2 {type uint8;}}"
+                                        "leaf ref1 {type leafref {path ../../toohigh;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path \"../../toohigh\" - too many \"..\" in the path. /bb:ref1");
+    assert_null(lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;container a {leaf target2 {type uint8;}}"
+                                        "leaf ref1 {type leafref {path /a:invalid;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path - unable to find module connected with the prefix of the node \"/a:invalid\". /cc:ref1");
+    assert_null(lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;leaf target1 {type string;}container a {leaf target2 {type uint8;}}"
+                                        "leaf ref1 {type leafref {path '/a[target2 = current()/../target1]/target2';}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path - node \"/a\" is expected to be a list, but it is container. /dd:ref1");
+    assert_null(lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;container a {leaf target2 {type uint8;}}"
+                                        "leaf ref1 {type leafref {path /a!invalid;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path at character 3 (/a!invalid). /ee:ref1");
+    assert_null(lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;container a {leaf target2 {type uint8;}}"
+                                        "leaf ref1 {type leafref {path /a;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path \"/a\" - target node is container instead of leaf or leaf-list. /ff:ref1");
+    assert_null(lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;container a {leaf target2 {type uint8; status deprecated;}}"
+                                        "leaf ref1 {type leafref {path /a/target2;}}}", LYS_IN_YANG));
+    logbuf_assert("A current definition \"ref1\" is not allowed to reference deprecated definition \"target2\". /gg:ref1");
+    assert_null(lys_parse_mem(ctx, "module hh {namespace urn:hh;prefix hh;"
+                                        "leaf ref1 {type leafref;}}", LYS_IN_YANG));
+    logbuf_assert("Missing path substatement for leafref type. /hh:ref1");
+    assert_null(lys_parse_mem(ctx, "module ii {namespace urn:ii;prefix ii;typedef mytype {type leafref;}"
+                                        "leaf ref1 {type mytype;}}", LYS_IN_YANG));
+    logbuf_assert("Missing path substatement for leafref type mytype. /ii:ref1");
+    assert_null(lys_parse_mem(ctx, "module jj {namespace urn:jj;prefix jj;feature f;"
+                                        "leaf ref {type leafref {path /target;}}leaf target {if-feature f;type string;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path \"/target\" - set of features applicable to the leafref target is not a subset of features "
+                  "applicable to the leafref itself. /jj:ref");
+    assert_null(lys_parse_mem(ctx, "module kk {namespace urn:kk;prefix kk;"
+                                        "leaf ref {type leafref {path /target;}}leaf target {type string;config false;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path \"/target\" - target is supposed to represent configuration data (as the leafref does), but it does not. /kk:ref");
+
+    assert_null(lys_parse_mem(ctx, "module ll {namespace urn:ll;prefix ll;"
+                                        "leaf ref {type leafref {path /target; require-instance true;}}leaf target {type string;}}", LYS_IN_YANG));
+    logbuf_assert("Leafref type can be restricted by require-instance statement only in YANG 1.1 modules. /ll:ref");
+    assert_null(lys_parse_mem(ctx, "module mm {namespace urn:mm;prefix mm;typedef mytype {type leafref {path /target;require-instance false;}}"
+                                        "leaf ref {type mytype;}leaf target {type string;}}", LYS_IN_YANG));
+    logbuf_assert("Leafref type \"mytype\" can be restricted by require-instance statement only in YANG 1.1 modules. /mm:ref");
+
+    assert_null(lys_parse_mem(ctx, "module nn {namespace urn:nn;prefix nn;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}"
+                                        "leaf address {type leafref{ path \"/interface[name is current()/../ifname]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[name i\" - missing \"=\" after node-identifier. /nn:address");
+
+    assert_null(lys_parse_mem(ctx, "module oo {namespace urn:oo;prefix oo;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}"
+                                        "leaf address {type leafref{ path \"/interface[name=current()/../ifname/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[name=current()/../ifname/ip\" - missing predicate termination. /oo:address");
+
+    assert_null(lys_parse_mem(ctx, "module pp {namespace urn:pp;prefix pp;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}"
+                                        "leaf address {type leafref{ path \"/interface[x:name=current()/../ifname]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[x:name=current()/../ifname]\" - prefix \"x\" not defined in module \"pp\". /pp:address");
+
+    assert_null(lys_parse_mem(ctx, "module qq {namespace urn:qq;prefix qq;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}"
+                                        "leaf address {type leafref{ path \"/interface[id=current()/../ifname]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[id=current()/../ifname]\" - predicate's key node \"id\" not found. /qq:address");
+
+    assert_null(lys_parse_mem(ctx, "module rr {namespace urn:rr;prefix rr;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+                                        "leaf address {type leafref{ path \"/interface[name=current() /  .. / ifname][name=current()/../test]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[name=current()/../test]\" - multiple equality tests for the key \"name\". /rr:address");
+
+    assert_null(lys_parse_mem(ctx, "module ss {namespace urn:ss;prefix ss;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+                                        "leaf address {type leafref{ path \"/interface[name = ../ifname]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[name = ../ifname]\" - missing current-function-invocation. /ss:address");
+
+    assert_null(lys_parse_mem(ctx, "module tt {namespace urn:tt;prefix tt;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+                                        "leaf address {type leafref{ path \"/interface[name = current()../ifname]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[name = current()../ifname]\" - missing \"/\" after current-function-invocation. /tt:address");
+
+    assert_null(lys_parse_mem(ctx, "module uu {namespace urn:uu;prefix uu;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+                                        "leaf address {type leafref{ path \"/interface[name = current()/..ifname]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[name = current()/..ifname]\" - missing \"/\" in \"../\" rel-path-keyexpr pattern. /uu:address");
+
+    assert_null(lys_parse_mem(ctx, "module vv {namespace urn:vv;prefix vv;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+                                        "leaf address {type leafref{ path \"/interface[name = current()/ifname]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[name = current()/ifname]\" - at least one \"..\" is expected in rel-path-keyexpr. /vv:address");
+
+    assert_null(lys_parse_mem(ctx, "module ww {namespace urn:ww;prefix ww;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+                                        "leaf address {type leafref{ path \"/interface[name = current()/../]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[name = current()/../]\" - at least one node-identifier is expected in rel-path-keyexpr. /ww:address");
+
+    assert_null(lys_parse_mem(ctx, "module xx {namespace urn:xx;prefix xx;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}leaf test{type string;}"
+                                        "leaf address {type leafref{ path \"/interface[name = current()/../$node]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid node identifier in leafref path predicate - character 22 (of [name = current()/../$node]). /xx:address");
+
+    assert_null(lys_parse_mem(ctx, "module yy {namespace urn:yy;prefix yy;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}"
+                                        "leaf address {type leafref{ path \"/interface[name=current()/../x:ifname]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[name=current()/../x:ifname]\" - unable to find module of the node \"ifname\" in rel-path-keyexpr. /yy:address");
+
+    assert_null(lys_parse_mem(ctx, "module zz {namespace urn:zz;prefix zz;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}"
+                                        "leaf address {type leafref{ path \"/interface[name=current()/../xxx]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[name=current()/../xxx]\" - unable to find node \"current()/../xxx\" in the rel-path-keyexpr. /zz:address");
+
+    assert_null(lys_parse_mem(ctx, "module zza {namespace urn:zza;prefix zza;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}container c;"
+                                        "leaf address {type leafref{ path \"/interface[name=current()/../c]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[name=current()/../c]\" - rel-path-keyexpr \"current()/../c\" refers container instead of leaf. /zza:address");
+
+    assert_null(lys_parse_mem(ctx, "module zzb {namespace urn:zzb;prefix zzb;"
+                                        "list interface{key name;leaf name{type string;}leaf ip {type string;}container c;}"
+                                        "leaf ifname{type leafref{ path \"../interface/name\";}}"
+                                        "leaf address {type leafref{ path \"/interface[c=current()/../ifname]/ip\";}}}",
+                                        LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path predicate \"[c=current()/../ifname]\" - predicate's key node \"c\" not found. /zzb:address");
+
+    assert_null(lys_parse_mem(ctx, "module zzc {namespace urn:zzc;prefix zzc;"
+                                        "leaf source {type leafref {path \"../target\";}default true;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path - unable to find \"../target\". /zzc:source");
+
+    assert_null(lys_parse_mem(ctx, "module zzd {namespace urn:zzd;prefix zzd;"
+                                        "leaf source {type leafref {path \"../target\";}default true;}"
+                                        "leaf target {type uint8;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid default - value does not fit the type (Invalid uint8 value \"true\".). /zzd:source");
+
+    /* circular chain */
+    assert_null(lys_parse_mem(ctx, "module aaa {namespace urn:aaa;prefix aaa;"
+                                        "leaf ref1 {type leafref {path /ref2;}}"
+                                        "leaf ref2 {type leafref {path /ref3;}}"
+                                        "leaf ref3 {type leafref {path /ref4;}}"
+                                        "leaf ref4 {type leafref {path /ref1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid leafref path \"/ref1\" - circular chain of leafrefs detected. /aaa:ref4");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_empty(void **state)
+{
+    *state = test_type_empty;
+
+    struct ly_ctx *ctx;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    /* invalid */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;"
+                                        "leaf l {type empty; default x;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid leaf's default value \"x\" which does not fit the type (Invalid empty value \"x\".). /aa:l");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;typedef mytype {type empty; default x;}"
+                                        "leaf l {type mytype;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid type \"mytype\" - \"empty\" type must not have a default value (x). /bb:l");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_union(void **state)
+{
+    *state = test_type_union;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_type *type;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1;namespace urn:a;prefix a; typedef mybasetype {type string;}"
+                                        "typedef mytype {type union {type int8; type mybasetype;}}"
+                                        "leaf l {type mytype;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(2, type->refcount);
+    assert_int_equal(LY_TYPE_UNION, type->basetype);
+    assert_non_null(((struct lysc_type_union*)type)->types);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_union*)type)->types));
+    assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_union*)type)->types[0]->basetype);
+    assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_union*)type)->types[1]->basetype);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1;namespace urn:b;prefix b; typedef mybasetype {type string;}"
+                                        "typedef mytype {type union {type int8; type mybasetype;}}"
+                                        "leaf l {type union {type decimal64 {fraction-digits 2;} type mytype;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_UNION, type->basetype);
+    assert_non_null(((struct lysc_type_union*)type)->types);
+    assert_int_equal(3, LY_ARRAY_SIZE(((struct lysc_type_union*)type)->types));
+    assert_int_equal(LY_TYPE_DEC64, ((struct lysc_type_union*)type)->types[0]->basetype);
+    assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_union*)type)->types[1]->basetype);
+    assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_union*)type)->types[2]->basetype);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module c {yang-version 1.1;namespace urn:c;prefix c; typedef mybasetype {type string;}"
+                                        "typedef mytype {type union {type leafref {path ../target;} type mybasetype;}}"
+                                        "leaf l {type union {type decimal64 {fraction-digits 2;} type mytype;}}"
+                                        "leaf target {type leafref {path ../realtarget;}} leaf realtarget {type int8;}}",
+                                        LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_UNION, type->basetype);
+    assert_non_null(((struct lysc_type_union*)type)->types);
+    assert_int_equal(3, LY_ARRAY_SIZE(((struct lysc_type_union*)type)->types));
+    assert_int_equal(LY_TYPE_DEC64, ((struct lysc_type_union*)type)->types[0]->basetype);
+    assert_int_equal(LY_TYPE_LEAFREF, ((struct lysc_type_union*)type)->types[1]->basetype);
+    assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_union*)type)->types[2]->basetype);
+    assert_non_null(((struct lysc_type_leafref*)((struct lysc_type_union*)type)->types[1])->realtype);
+    assert_int_equal(LY_TYPE_INT8, ((struct lysc_type_leafref*)((struct lysc_type_union*)type)->types[1])->realtype->basetype);
+
+    /* invalid unions */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;typedef mytype {type union;}"
+                                        "leaf l {type mytype;}}", LYS_IN_YANG));
+    logbuf_assert("Missing type substatement for union type mytype. /aa:l");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;leaf l {type union;}}", LYS_IN_YANG));
+   logbuf_assert("Missing type substatement for union type. /bb:l");
+
+    assert_null(lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;typedef mytype {type union{type int8; type string;}}"
+                                        "leaf l {type mytype {type string;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid type substatement for the type not directly derived from union built-in type. /cc:l");
+
+    assert_null(lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;typedef mytype {type union{type int8; type string;}}"
+                                        "typedef mytype2 {type mytype {type string;}}leaf l {type mytype2;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid type substatement for the type \"mytype2\" not directly derived from union built-in type. /dd:l");
+
+    assert_null(lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;typedef mytype {type union{type mytype; type string;}}"
+                                        "leaf l {type mytype;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid \"mytype\" type reference - circular chain of types detected. /ee:l");
+    assert_null(lys_parse_mem(ctx, "module ef {namespace urn:ef;prefix ef;typedef mytype {type mytype2;}"
+                                        "typedef mytype2 {type mytype;} leaf l {type mytype;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid \"mytype\" type reference - circular chain of types detected. /ef:l");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_type_dflt(void **state)
+{
+    *state = test_type_union;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_type *type;
+    struct lysc_node_leaf *leaf;
+    int dynamic;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    /* default is not inherited from union's types */
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a; typedef mybasetype {type string;default hello;units xxx;}"
+                                        "leaf l {type union {type decimal64 {fraction-digits 2;} type mybasetype;}}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(1, type->refcount);
+    assert_int_equal(LY_TYPE_UNION, type->basetype);
+    assert_non_null(((struct lysc_type_union*)type)->types);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_union*)type)->types));
+    assert_int_equal(LY_TYPE_DEC64, ((struct lysc_type_union*)type)->types[0]->basetype);
+    assert_int_equal(LY_TYPE_STRING, ((struct lysc_type_union*)type)->types[1]->basetype);
+    assert_null(((struct lysc_node_leaf*)mod->compiled->data)->dflt);
+    assert_null(((struct lysc_node_leaf*)mod->compiled->data)->units);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b; typedef mybasetype {type string;default hello;units xxx;}"
+                                        "leaf l {type mybasetype;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(3, type->refcount); /* 2x type reference, 1x default value's reference (typedf's default does not reference own type)*/
+    assert_int_equal(LY_TYPE_STRING, type->basetype);
+    assert_non_null(leaf = (struct lysc_node_leaf*)mod->compiled->data);
+    assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_string_equal("xxx", leaf->units);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c; typedef mybasetype {type string;default hello;units xxx;}"
+                                        "leaf l {type mybasetype; default goodbye;units yyy;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(3, type->refcount); /* 2x type reference, 1x default value's reference */
+    assert_int_equal(LY_TYPE_STRING, type->basetype);
+    leaf = (struct lysc_node_leaf*)mod->compiled->data;
+    assert_string_equal("goodbye", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_string_equal("yyy", leaf->units);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d; typedef mybasetype {type string;default hello;units xxx;}"
+                                        "typedef mytype {type mybasetype;}leaf l1 {type mytype; default goodbye;units yyy;}"
+                                        "leaf l2 {type mytype;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(6, type->refcount); /* 4x type reference, 2x default value's reference (1 shared compiled type of typedefs which default does not reference own type) */
+    assert_int_equal(LY_TYPE_STRING, type->basetype);
+    leaf = (struct lysc_node_leaf*)mod->compiled->data;
+    assert_string_equal("goodbye", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_string_equal("yyy", leaf->units);
+    type = ((struct lysc_node_leaf*)mod->compiled->data->next)->type;
+    assert_non_null(type);
+    assert_int_equal(6, type->refcount); /* 4x type reference, 2x default value's reference (1 shared compiled type of typedefs which default does not reference own type) */
+    assert_int_equal(LY_TYPE_STRING, type->basetype);
+    leaf = (struct lysc_node_leaf*)mod->compiled->data->next;
+    assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_string_equal("xxx", leaf->units);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module e {namespace urn:e;prefix e; typedef mybasetype {type string;}"
+                                        "typedef mytype {type mybasetype; default hello;units xxx;}leaf l {type mytype;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(4, type->refcount); /* 3x type reference, 1x default value's reference (typedef's default does not reference own type) */
+    assert_int_equal(LY_TYPE_STRING, type->basetype);
+    leaf = (struct lysc_node_leaf*)mod->compiled->data;
+    assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_string_equal("xxx", leaf->units);
+
+    /* mandatory leaf does not takes default value from type */
+    assert_non_null(mod = lys_parse_mem(ctx, "module f {namespace urn:f;prefix f;typedef mytype {type string; default hello;units xxx;}"
+                                        "leaf l {type mytype; mandatory true;}}", LYS_IN_YANG));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_STRING, type->basetype);
+    assert_null(((struct lysc_node_leaf*)mod->compiled->data)->dflt);
+    assert_string_equal("xxx", ((struct lysc_node_leaf*)mod->compiled->data)->units);
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_status(void **state)
+{
+    *state = test_status;
+
+    struct ly_ctx *ctx;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;"
+                                        "container c {status deprecated; leaf l {status current; type string;}}}", LYS_IN_YANG));
+    logbuf_assert("A \"current\" status is in conflict with the parent's \"deprecated\" status. /aa:c/l");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;"
+                                        "container c {status obsolete; leaf l {status current; type string;}}}", LYS_IN_YANG));
+    logbuf_assert("A \"current\" status is in conflict with the parent's \"obsolete\" status. /bb:c/l");
+
+    assert_null(lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;"
+                                        "container c {status obsolete; leaf l {status deprecated; type string;}}}", LYS_IN_YANG));
+    logbuf_assert("A \"deprecated\" status is in conflict with the parent's \"obsolete\" status. /cc:c/l");
+
+    assert_null(lys_parse_mem(ctx, "module cc {namespace urn:dd;prefix d;"
+                                        "container c {leaf l {status obsolete; type string;}}"
+                                        "container d {leaf m {when \"../../c/l\"; type string;}}}", LYS_IN_YANG));
+    logbuf_assert("A current definition \"m\" is not allowed to reference obsolete definition \"l\". /cc:d/m");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_grouping(void **state)
+{
+    *state = test_grouping;
+
+    struct ly_ctx *ctx;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    /* result ok, but a warning about not used locally scoped grouping printed */
+    assert_non_null(lys_parse_mem(ctx, "module a {namespace urn:a;prefix a; grouping grp1 {leaf a1 {type string;}}"
+                                  "container a {leaf x {type string;} grouping grp2 {leaf a2 {type string;}}}}", LYS_IN_YANG));
+    logbuf_assert("Locally scoped grouping \"grp2\" not used.");
+    logbuf_clean();
+
+    /* result ok - when statement or leafref target must be checked only at the place where the grouping is really instantiated */
+    assert_non_null(lys_parse_mem(ctx, "module b {namespace urn:b;prefix b; grouping grp {"
+                                  "leaf ref {type leafref {path \"../name\";}}"
+                                  "leaf cond {type string; when \"../name = 'specialone'\";}}}", LYS_IN_YANG));
+    logbuf_assert("");
+
+
+    /* invalid - error in a non-instantiated grouping */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;"
+                                        "grouping grp {leaf x {type leafref;}}}", LYS_IN_YANG));
+    logbuf_assert("Missing path substatement for leafref type. /aa:{grouping='grp'}/x");
+    logbuf_clean();
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;"
+                                        "container a {grouping grp {leaf x {type leafref;}}}}", LYS_IN_YANG));
+    logbuf_assert("Missing path substatement for leafref type. /aa:a/{grouping='grp'}/x");
+
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_uses(void **state)
+{
+    *state = test_uses;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    const struct lysc_node *parent, *child;
+    const struct lysc_node_container *cont;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module grp {namespace urn:grp;prefix g; typedef mytype {type string;} feature f;"
+                              "grouping grp {leaf x {type mytype;} leaf y {type string; if-feature f;}}}");
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {namespace urn:a;prefix a;import grp {prefix g;}"
+                                        "grouping grp_a_top {leaf a1 {type int8;}}"
+                                        "container a {uses grp_a; uses grp_a_top; uses g:grp; grouping grp_a {leaf a2 {type uint8;}}}}", LYS_IN_YANG));
+    assert_non_null((parent = mod->compiled->data));
+    assert_int_equal(LYS_CONTAINER, parent->nodetype);
+    assert_non_null((child = ((struct lysc_node_container*)parent)->child));
+    assert_string_equal("a2", child->name);
+    assert_ptr_equal(mod, child->module);
+    assert_non_null((child = child->next));
+    assert_string_equal("a1", child->name);
+    assert_ptr_equal(mod, child->module);
+    assert_non_null((child = child->next));
+    assert_string_equal("x", child->name);
+    assert_ptr_equal(mod, child->module);
+    assert_non_null((child = child->next));
+    assert_string_equal("y", child->name);
+    assert_non_null(child->iffeatures);
+    assert_int_equal(1, LY_ARRAY_SIZE(child->iffeatures));
+    assert_int_equal(1, LY_ARRAY_SIZE(child->iffeatures[0].features));
+    assert_string_equal("f", child->iffeatures[0].features[0]->name);
+    assert_int_equal(LY_EINVAL, lys_feature_enable(mod->compiled->imports[0].module, "f"));
+    logbuf_assert("Module \"grp\" is not implemented so all its features are permanently disabled without a chance to change it.");
+    assert_int_equal(0, lysc_iffeature_value(&child->iffeatures[0]));
+
+    /* make the imported module implemented and enable the feature */
+    assert_non_null(mod = ly_ctx_get_module(ctx, "grp", NULL));
+    assert_int_equal(LY_SUCCESS, lys_set_implemented(mod));
+    assert_int_equal(LY_SUCCESS, lys_feature_enable(mod, "f"));
+    assert_string_equal("f", child->iffeatures[0].features[0]->name);
+    assert_int_equal(1, lysc_iffeature_value(&child->iffeatures[0]));
+
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule bsub {belongs-to b {prefix b;} grouping grp {leaf b {when 1; type string;} leaf c {type string;}}}");
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;include bsub;uses grp {when 2;}}", LYS_IN_YANG));
+    assert_non_null(mod->compiled->data);
+    assert_int_equal(LYS_LEAF, mod->compiled->data->nodetype);
+    assert_string_equal("b", mod->compiled->data->name);
+    assert_int_equal(2, LY_ARRAY_SIZE(mod->compiled->data->when));
+    assert_int_equal(1, mod->compiled->data->when[0]->refcount);
+    assert_non_null(mod->compiled->data->when[0]->context);
+    assert_string_equal("b", mod->compiled->data->when[0]->context->name);
+    assert_int_equal(2, mod->compiled->data->when[1]->refcount);
+    assert_null(mod->compiled->data->when[1]->context);
+
+    assert_int_equal(LYS_LEAF, mod->compiled->data->next->nodetype);
+    assert_string_equal("c", mod->compiled->data->next->name);
+    assert_int_equal(1, LY_ARRAY_SIZE(mod->compiled->data->next->when));
+    assert_int_equal(2, mod->compiled->data->next->when[0]->refcount);
+    assert_null(mod->compiled->data->next->when[0]->context);
+
+    logbuf_clean();
+    assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:ii;prefix ii;"
+                                        "grouping grp {leaf l {type string;}leaf k {type string; status obsolete;}}"
+                                        "uses grp {status deprecated;}}", LYS_IN_YANG));
+    assert_int_equal(LYS_LEAF, mod->compiled->data->nodetype);
+    assert_string_equal("l", mod->compiled->data->name);
+    assert_true(LYS_STATUS_DEPRC & mod->compiled->data->flags);
+    assert_int_equal(LYS_LEAF, mod->compiled->data->next->nodetype);
+    assert_string_equal("k", mod->compiled->data->next->name);
+    assert_true(LYS_STATUS_OBSLT & mod->compiled->data->next->flags);
+    logbuf_assert(""); /* no warning about inheriting deprecated flag from uses */
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d; grouping grp {container g;}"
+                                        "container top {uses grp {augment g {leaf x {type int8;}}}}}", LYS_IN_YANG));
+    assert_non_null(mod->compiled->data);
+    assert_non_null(child = lysc_node_children(mod->compiled->data, 0));
+    assert_string_equal("g", child->name);
+    assert_non_null(child = lysc_node_children(child, 0));
+    assert_string_equal("x", child->name);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module e {yang-version 1.1;namespace urn:e;prefix e; grouping grp {action g { description \"super g\";}}"
+                                        "container top {action e; uses grp {refine g {description \"ultra g\";}}}}", LYS_IN_YANG));
+    assert_non_null(mod->compiled->data);
+    cont = (const struct lysc_node_container*)mod->compiled->data;
+    assert_non_null(cont->actions);
+    assert_int_equal(2, LY_ARRAY_SIZE(cont->actions));
+    assert_string_equal("e", cont->actions[1].name);
+    assert_string_equal("g", cont->actions[0].name);
+    assert_string_equal("ultra g", cont->actions[0].dsc);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module f {yang-version 1.1;namespace urn:f;prefix f; grouping grp {notification g { description \"super g\";}}"
+                                        "container top {notification f; uses grp {refine g {description \"ultra g\";}}}}", LYS_IN_YANG));
+    assert_non_null(mod->compiled->data);
+    cont = (const struct lysc_node_container*)mod->compiled->data;
+    assert_non_null(cont->notifs);
+    assert_int_equal(2, LY_ARRAY_SIZE(cont->notifs));
+    assert_string_equal("f", cont->notifs[1].name);
+    assert_string_equal("g", cont->notifs[0].name);
+    assert_string_equal("ultra g", cont->notifs[0].dsc);
+
+    /* empty grouping */
+    assert_non_null(mod = lys_parse_mem(ctx, "module g {namespace urn:g;prefix g; grouping grp; uses grp;}", LYS_IN_YANG));
+    assert_null(mod->compiled->data);
+
+    /* invalid */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;uses missinggrp;}", LYS_IN_YANG));
+    logbuf_assert("Grouping \"missinggrp\" referenced by a uses statement not found. /aa:{uses='missinggrp'}");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;uses grp;"
+                                        "grouping grp {leaf a{type string;}uses grp1;}"
+                                        "grouping grp1 {leaf b {type string;}uses grp2;}"
+                                        "grouping grp2 {leaf c {type string;}uses grp;}}", LYS_IN_YANG));
+    logbuf_assert("Grouping \"grp\" references itself through a uses statement. /bb:{uses='grp'}/{uses='grp1'}/{uses='grp2'}/{uses='grp'}");
+
+    assert_null(lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;uses a:missingprefix;}", LYS_IN_YANG));
+    logbuf_assert("Invalid prefix used for grouping reference. /cc:{uses='a:missingprefix'}");
+
+    assert_null(lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;grouping grp{leaf a{type string;}}"
+                                        "leaf a {type string;}uses grp;}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"a\" of data definition/RPC/action/notification statement. /dd:{uses='grp'}/dd:a");
+
+    assert_null(lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;grouping grp {leaf l {type string; status deprecated;}}"
+                                        "uses grp {status obsolete;}}", LYS_IN_YANG));
+    logbuf_assert("A \"deprecated\" status is in conflict with the parent's \"obsolete\" status. /ee:{uses='grp'}/ee:l");
+
+    assert_null(lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;grouping grp {leaf l {type string;}}"
+                                        "leaf l {type int8;}uses grp;}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"l\" of data definition/RPC/action/notification statement. /ff:{uses='grp'}/ff:l");
+    assert_null(lys_parse_mem(ctx, "module fg {namespace urn:fg;prefix fg;grouping grp {leaf m {type string;}}"
+                                        "uses grp;leaf m {type int8;}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"m\" of data definition/RPC/action/notification statement. /fg:m");
+
+
+    assert_null(lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg; grouping grp {container g;}"
+                              "leaf g {type string;}"
+                              "container top {uses grp {augment /g {leaf x {type int8;}}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid descendant-schema-nodeid value \"/g\" - absolute-schema-nodeid used. /gg:top/{uses='grp'}/{augment='/g'}");
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module hh {yang-version 1.1;namespace urn:hh;prefix hh;"
+                                        "grouping grp {notification g { description \"super g\";}}"
+                                        "container top {notification h; uses grp {refine h {description \"ultra h\";}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid descendant-schema-nodeid value \"h\" - target node not found. /hh:top/{uses='grp'}/{refine='h'}");
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module ii {yang-version 1.1;namespace urn:ii;prefix ii;"
+                                        "grouping grp {action g { description \"super g\";}}"
+                                        "container top {action i; uses grp {refine i {description \"ultra i\";}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid descendant-schema-nodeid value \"i\" - target node not found. /ii:top/{uses='grp'}/{refine='i'}");
+
+    assert_null(lys_parse_mem(ctx, "module jj {yang-version 1.1;namespace urn:jj;prefix jj;"
+                              "grouping grp {leaf j { when \"1\"; type invalid;}}"
+                              "container top {uses grp;}}", LYS_IN_YANG));
+    logbuf_assert("Referenced type \"invalid\" not found. /jj:top/{uses='grp'}/j");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_refine(void **state)
+{
+    *state = test_refine;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lysc_node *parent, *child;
+    struct lysc_node_leaf *leaf;
+    struct lysc_node_leaflist *llist;
+    int dynamic;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_non_null(lys_parse_mem(ctx, "module grp {yang-version 1.1;namespace urn:grp;prefix g; feature f;typedef mytype {type string; default cheers!;}"
+                                       "grouping grp {container c {leaf l {type mytype; default goodbye;}"
+                                       "leaf-list ll {type mytype; default goodbye; max-elements 6;}"
+                                       "choice ch {default a; leaf a {type int8;}leaf b{type uint8;}}"
+                                       "leaf x {type mytype; mandatory true; must 1;}"
+                                       "anydata a {mandatory false; if-feature f; description original; reference original;}"
+                                       "container c {config false; leaf l {type string;}}}}}", LYS_IN_YANG));
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module a {yang-version 1.1;namespace urn:a;prefix a;import grp {prefix g;}feature fa;"
+                                        "uses g:grp {refine c/l {default hello; config false;}"
+                                        "refine c/ll {default hello;default world; min-elements 2; max-elements 5;}"
+                                        "refine c/ch {default b;config true; if-feature fa;}"
+                                        "refine c/x {mandatory false; must ../ll;description refined; reference refined;}"
+                                        "refine c/a {mandatory true; must 1; if-feature fa;description refined; reference refined;}"
+                                        "refine c/c {config true;presence indispensable;}}}", LYS_IN_YANG));
+    assert_non_null((parent = mod->compiled->data));
+    assert_int_equal(LYS_CONTAINER, parent->nodetype);
+    assert_string_equal("c", parent->name);
+    assert_non_null((leaf = (struct lysc_node_leaf*)((struct lysc_node_container*)parent)->child));
+    assert_int_equal(LYS_LEAF, leaf->nodetype);
+    assert_string_equal("l", leaf->name);
+    assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_int_equal(LYS_CONFIG_R, leaf->flags & LYS_CONFIG_MASK);
+    assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+    assert_int_equal(LYS_LEAFLIST, llist->nodetype);
+    assert_string_equal("ll", llist->name);
+    assert_int_equal(2, LY_ARRAY_SIZE(llist->dflts));
+    assert_string_equal("hello", llist->dflts[0]->realtype->plugin->print(llist->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_string_equal("world", llist->dflts[1]->realtype->plugin->print(llist->dflts[1], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_int_equal(2, llist->min);
+    assert_int_equal(5, llist->max);
+    assert_non_null(child = llist->next);
+    assert_int_equal(LYS_CHOICE, child->nodetype);
+    assert_string_equal("ch", child->name);
+    assert_string_equal("b", ((struct lysc_node_choice*)child)->dflt->name);
+    assert_true(LYS_SET_DFLT & ((struct lysc_node_choice*)child)->dflt->flags);
+    assert_false(LYS_SET_DFLT & ((struct lysc_node_choice*)child)->cases[0].flags);
+    assert_non_null(child->iffeatures);
+    assert_int_equal(1, LY_ARRAY_SIZE(child->iffeatures));
+    assert_non_null(leaf = (struct lysc_node_leaf*)child->next);
+    assert_int_equal(LYS_LEAF, leaf->nodetype);
+    assert_string_equal("x", leaf->name);
+    assert_false(LYS_MAND_TRUE & leaf->flags);
+    assert_string_equal("cheers!", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_non_null(leaf->musts);
+    assert_int_equal(2, LY_ARRAY_SIZE(leaf->musts));
+    assert_string_equal("refined", leaf->dsc);
+    assert_string_equal("refined", leaf->ref);
+    assert_non_null(child = leaf->next);
+    assert_int_equal(LYS_ANYDATA, child->nodetype);
+    assert_string_equal("a", child->name);
+    assert_true(LYS_MAND_TRUE & child->flags);
+    assert_non_null(((struct lysc_node_anydata*)child)->musts);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_node_anydata*)child)->musts));
+    assert_non_null(child->iffeatures);
+    assert_int_equal(2, LY_ARRAY_SIZE(child->iffeatures));
+    assert_string_equal("refined", child->dsc);
+    assert_string_equal("refined", child->ref);
+    assert_non_null(child = child->next);
+    assert_int_equal(LYS_CONTAINER, child->nodetype);
+    assert_string_equal("c", child->name);
+    assert_true(LYS_PRESENCE & child->flags);
+    assert_true(LYS_CONFIG_W & child->flags);
+    assert_true(LYS_CONFIG_W & ((struct lysc_node_container*)child)->child->flags);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {yang-version 1.1;namespace urn:b;prefix b;import grp {prefix g;}"
+                                        "uses g:grp {status deprecated; refine c/x {default hello; mandatory false;}}}", LYS_IN_YANG));
+    assert_non_null((leaf = (struct lysc_node_leaf*)((struct lysc_node_container*)mod->compiled->data)->child->prev->prev->prev));
+    assert_int_equal(LYS_LEAF, leaf->nodetype);
+    assert_string_equal("x", leaf->name);
+    assert_false(LYS_MAND_TRUE & leaf->flags);
+    assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+
+    /* invalid */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa;import grp {prefix g;}"
+                                        "uses g:grp {refine c {default hello;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of default - container cannot hold default value(s). /aa:{uses='g:grp'}/{refine='c'}");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;import grp {prefix g;}"
+                                        "uses g:grp {refine c/l {default hello; default world;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of default - leaf cannot hold 2 default values. /bb:{uses='g:grp'}/{refine='c/l'}");
+
+    assert_null(lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;import grp {prefix g;}"
+                                        "uses g:grp {refine c/ll {default hello; default world;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of default in leaf-list - the default statement is allowed only in YANG 1.1 modules. /cc:{uses='g:grp'}/{refine='c/ll'}");
+
+    assert_null(lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;import grp {prefix g;}"
+                                        "uses g:grp {refine c/ll {mandatory true;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of mandatory - leaf-list cannot hold mandatory statement. /dd:{uses='g:grp'}/{refine='c/ll'}");
+
+    assert_null(lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;import grp {prefix g;}"
+                                        "uses g:grp {refine c/l {mandatory true;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of mandatory - leaf already has \"default\" statement. /ee:{uses='g:grp'}/{refine='c/l'}");
+    assert_null(lys_parse_mem(ctx, "module ef {namespace urn:ef;prefix ef;import grp {prefix g;}"
+                                        "uses g:grp {refine c/ch {mandatory true;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of mandatory - choice already has \"default\" statement. /ef:{uses='g:grp'}/{refine='c/ch'}");
+
+    assert_null(lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;import grp {prefix g;}"
+                                        "uses g:grp {refine c/ch/a/a {mandatory true;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of mandatory under the default case. /ff:{uses='g:grp'}/{refine='c/ch/a/a'}");
+
+    assert_null(lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg;import grp {prefix g;}"
+                                        "uses g:grp {refine c/x {default hello;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of default - the node is mandatory. /gg:{uses='g:grp'}/{refine='c/x'}");
+
+    assert_null(lys_parse_mem(ctx, "module hh {namespace urn:hh;prefix hh;import grp {prefix g;}"
+                                        "uses g:grp {refine c/c/l {config true;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of config - configuration node cannot be child of any state data node. /hh:{uses='g:grp'}/{refine='c/c/l'}");
+
+    assert_null(lys_parse_mem(ctx, "module ii {namespace urn:ii;prefix ii;grouping grp {leaf l {type string; status deprecated;}}"
+                                        "uses grp {status obsolete;}}", LYS_IN_YANG));
+    logbuf_assert("A \"deprecated\" status is in conflict with the parent's \"obsolete\" status. /ii:{uses='grp'}/ii:l");
+
+    assert_null(lys_parse_mem(ctx, "module jj {namespace urn:jj;prefix jj;import grp {prefix g;}"
+                                        "uses g:grp {refine c/x {presence nonsence;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of presence statement - leaf cannot hold the presence statement. /jj:{uses='g:grp'}/{refine='c/x'}");
+
+    assert_null(lys_parse_mem(ctx, "module kk {namespace urn:kk;prefix kk;import grp {prefix g;}"
+                                        "uses g:grp {refine c/ch {must 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of must statement - choice cannot hold any must statement. /kk:{uses='g:grp'}/{refine='c/ch'}");
+
+    assert_null(lys_parse_mem(ctx, "module ll {namespace urn:ll;prefix ll;import grp {prefix g;}"
+                                        "uses g:grp {refine c/x {min-elements 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of min-elements statement - leaf cannot hold this statement. /ll:{uses='g:grp'}/{refine='c/x'}");
+
+    assert_null(lys_parse_mem(ctx, "module mm {namespace urn:mm;prefix mm;import grp {prefix g;}"
+                                        "uses g:grp {refine c/ll {min-elements 10;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid refine of min-elements statement - \"min-elements\" is bigger than \"max-elements\". /mm:{uses='g:grp'}/{refine='c/ll'}");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_augment(void **state)
+{
+    *state = test_augment;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    const struct lysc_node *node;
+    const struct lysc_node_choice *ch;
+    const struct lysc_node_case *c;
+    const struct lysc_node_container *cont;
+    const struct lysc_action *rpc;
+    const struct lysc_notif *notif;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module a {namespace urn:a;prefix a; typedef atype {type string;}"
+                              "container top {leaf a {type string;}}}");
+    assert_non_null(lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;import a {prefix a;}"
+                                  "leaf b {type a:atype;}}", LYS_IN_YANG));
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module c {namespace urn:c;prefix c; import a {prefix a;}"
+                              "augment /a:top/ { container c {leaf c {type a:atype;}}}}");
+    assert_non_null(lys_parse_mem(ctx, "module d {namespace urn:d;prefix d;import a {prefix a;} import c {prefix c;}"
+                                  "augment /a:top/c:c/ { leaf d {type a:atype;} leaf c {type string;}}}", LYS_IN_YANG));
+    assert_non_null((mod = ly_ctx_get_module_implemented(ctx, "a")));
+    assert_non_null(ly_ctx_get_module_implemented(ctx, "b"));
+    assert_non_null(ly_ctx_get_module_implemented(ctx, "c"));
+    assert_non_null(ly_ctx_get_module_implemented(ctx, "d"));
+    assert_non_null(node = mod->compiled->data);
+    assert_string_equal(node->name, "top");
+    assert_non_null(node = lysc_node_children(node, 0));
+    assert_string_equal(node->name, "a");
+    assert_non_null(node = node->next);
+    assert_string_equal(node->name, "c");
+    assert_non_null(node = lysc_node_children(node, 0));
+    assert_string_equal(node->name, "c");
+    assert_non_null(node = node->next);
+    assert_string_equal(node->name, "d");
+    assert_non_null(node = node->next);
+    assert_string_equal(node->name, "c");
+
+    assert_non_null((mod = lys_parse_mem(ctx, "module e {namespace urn:e;prefix e;choice ch {leaf a {type string;}}"
+                                         "augment /ch/c {when 1; leaf lc2 {type uint16;}}"
+                                         "augment /ch { when 1; leaf b {type int8;} case c {leaf lc1 {type uint8;}}}}", LYS_IN_YANG)));
+    assert_non_null((ch = (const struct lysc_node_choice*)mod->compiled->data));
+    assert_null(mod->compiled->data->next);
+    assert_string_equal("ch", ch->name);
+    assert_non_null(c = ch->cases);
+    assert_string_equal("a", c->name);
+    assert_null(c->when);
+    assert_string_equal("a", c->child->name);
+    assert_non_null(c = (const struct lysc_node_case*)c->next);
+    assert_string_equal("b", c->name);
+    assert_non_null(c->when);
+    assert_string_equal("b", c->child->name);
+    assert_non_null(c = (const struct lysc_node_case*)c->next);
+    assert_string_equal("c", c->name);
+    assert_non_null(c->when);
+    assert_string_equal("lc1", ((const struct lysc_node_case*)c)->child->name);
+    assert_null(((const struct lysc_node_case*)c)->child->when);
+    assert_string_equal("lc2", ((const struct lysc_node_case*)c)->child->next->name);
+    assert_non_null(((const struct lysc_node_case*)c)->child->next->when);
+    assert_ptr_equal(ch->cases->child->prev, ((const struct lysc_node_case*)c)->child->next);
+    assert_null(c->next);
+
+    assert_non_null((mod = lys_parse_mem(ctx, "module f {namespace urn:f;prefix f;grouping g {leaf a {type string;}}"
+                                         "container c;"
+                                         "augment /c {uses g;}}", LYS_IN_YANG)));
+    assert_non_null(node = lysc_node_children(mod->compiled->data, 0));
+    assert_string_equal(node->name, "a");
+
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "submodule gsub {belongs-to g {prefix g;}"
+                                  "augment /c {container sub;}}");
+    assert_non_null(mod = lys_parse_mem(ctx, "module g {namespace urn:g;prefix g;include gsub; container c;"
+                                        "augment /c/sub {leaf main {type string;}}}", LYS_IN_YANG));
+    assert_non_null(mod->compiled->data);
+    assert_string_equal("c", mod->compiled->data->name);
+    assert_non_null(node = ((struct lysc_node_container*)mod->compiled->data)->child);
+    assert_string_equal("sub", node->name);
+    assert_non_null(node = ((struct lysc_node_container*)node)->child);
+    assert_string_equal("main", node->name);
+
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module himp {namespace urn:hi;prefix hi;container top; rpc func;}");
+    assert_non_null(mod = lys_parse_mem(ctx, "module h {namespace urn:h;prefix h;import himp {prefix hi;}container top;"
+                                        "augment /hi:top {container p {presence XXX; leaf x {mandatory true;type string;}}}"
+                                        "augment /hi:top {list ll {key x;leaf x {type string;}leaf y {mandatory true; type string;}}}"
+                                        "augment /hi:top {leaf l {type string; mandatory true; config false;}}"
+                                        "augment /top {leaf l {type string; mandatory true;}}}", LYS_IN_YANG));
+    assert_non_null(node = mod->compiled->data);
+    assert_non_null(node = ((struct lysc_node_container*)node)->child);
+    assert_string_equal("l", node->name);
+    assert_true(node->flags & LYS_MAND_TRUE);
+    assert_non_null(mod = ly_ctx_get_module_implemented(ctx, "himp"));
+    assert_non_null(node = mod->compiled->data);
+    assert_non_null(node = ((struct lysc_node_container*)node)->child);
+    assert_string_equal("p", node->name);
+    assert_non_null(node = node->next);
+    assert_string_equal("ll", node->name);
+    assert_non_null(node = node->next);
+    assert_string_equal("l", node->name);
+    assert_true(node->flags & LYS_CONFIG_R);
+
+    assert_non_null(lys_parse_mem(ctx, "module i {namespace urn:i;prefix i;import himp {prefix hi;}"
+                                        "augment /hi:func/input {leaf x {type string;}}"
+                                        "augment /hi:func/output {leaf y {type string;}}}", LYS_IN_YANG));
+    assert_non_null(mod = ly_ctx_get_module_implemented(ctx, "himp"));
+    assert_non_null(rpc = mod->compiled->rpcs);
+    assert_int_equal(1, LY_ARRAY_SIZE(rpc));
+    assert_non_null(rpc->input.data);
+    assert_string_equal("x", rpc->input.data->name);
+    assert_null(rpc->input.data->next);
+    assert_non_null(rpc->output.data);
+    assert_string_equal("y", rpc->output.data->name);
+    assert_null(rpc->output.data->next);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module j {namespace urn:j;prefix j;yang-version 1.1; container root;"
+                                        "grouping grp {notification grp-notif;}"
+                                        "augment /root {uses grp;}}", LYS_IN_YANG));
+    assert_non_null(cont = (const struct lysc_node_container*)mod->compiled->data);
+    assert_null(cont->child);
+    assert_non_null(notif = cont->notifs);
+    assert_int_equal(1, LY_ARRAY_SIZE(notif));
+
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; container c {leaf a {type string;}}"
+                                        "augment /x {leaf a {type int8;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid absolute-schema-nodeid value \"/x\" - target node not found. /aa:{augment='/x'}");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; container c {leaf a {type string;}}"
+                                        "augment /c {leaf a {type int8;}}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"a\" of data definition/RPC/action/notification statement. /bb:{augment='/c'}/a");
+
+
+    assert_null(lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc; container c {leaf a {type string;}}"
+                                        "augment /c/a {leaf a {type int8;}}}", LYS_IN_YANG));
+    logbuf_assert("Augment's absolute-schema-nodeid \"/c/a\" refers to a leaf node which is not an allowed augment's target. /cc:{augment='/c/a'}");
+
+    assert_null(lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd; container c {leaf a {type string;}}"
+                                        "augment /c {case b {leaf d {type int8;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid augment of container node which is not allowed to contain case node \"b\". /dd:{augment='/c'}");
+
+    assert_null(lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee; import himp {prefix hi;}"
+                                        "augment /hi:top {container c {leaf d {mandatory true; type int8;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid augment adding mandatory node \"c\" without making it conditional via when statement. /ee:{augment='/hi:top'}");
+
+    assert_null(lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff; container top;"
+                                        "augment ../top {leaf x {type int8;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid absolute-schema-nodeid value \"../top\" - missing starting \"/\". /ff:{augment='../top'}");
+
+    assert_null(lys_parse_mem(ctx, "module gg {namespace urn:gg;prefix gg; rpc func;"
+                                        "augment /func {leaf x {type int8;}}}", LYS_IN_YANG));
+    logbuf_assert("Augment's absolute-schema-nodeid \"/func\" refers to a RPC node which is not an allowed augment's target. /gg:{augment='/func'}");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_deviation(void **state)
+{
+    *state = test_deviation;
+
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    const struct lysc_node *node;
+    const struct lysc_node_list *list;
+    const struct lysc_node_leaflist *llist;
+    const struct lysc_node_leaf *leaf;
+    const char *str;
+    int dynamic;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module a {namespace urn:a;prefix a;"
+                              "container top {leaf a {type string;} leaf b {type string;} leaf c {type string;}}"
+                              "choice ch {default c; case b {leaf b{type string;}} case a {leaf a{type string;} leaf x {type string;}}"
+                              " case c {leaf c{type string;}}}"
+                              "rpc func1 { input { leaf x {type int8;}} output {leaf y {type int8;}}}"
+                              "rpc func2;}");
+    assert_non_null(lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;import a {prefix a;}"
+                                  "deviation /a:top/a:b {deviate not-supported;}"
+                                  "deviation /a:ch/a:a/a:x {deviate not-supported;}"
+                                  "deviation /a:ch/a:c/a:c {deviate not-supported;}"
+                                  "deviation /a:ch/a:b {deviate not-supported;}"
+                                  "deviation /a:ch/a:a/a:a {deviate not-supported;}"
+                                  "deviation /a:func1/a:input {deviate not-supported;}"
+                                  "deviation /a:func1/a:output {deviate not-supported;}"
+                                  "deviation /a:func2 {deviate not-supported;}}", LYS_IN_YANG));
+    assert_non_null((mod = ly_ctx_get_module_implemented(ctx, "a")));
+    assert_non_null(node = mod->compiled->data);
+    assert_string_equal(node->name, "top");
+    assert_non_null(node = lysc_node_children(node, 0));
+    assert_string_equal(node->name, "a");
+    assert_non_null(node = node->next);
+    assert_string_equal(node->name, "c");
+    assert_null(node = node->next);
+    assert_non_null(node = mod->compiled->data->next);
+    assert_string_equal("ch", node->name);
+    assert_null(((struct lysc_node_choice*)node)->dflt);
+    assert_null(((struct lysc_node_choice*)node)->cases);
+    assert_int_equal(1, LY_ARRAY_SIZE(mod->compiled->rpcs));
+    assert_null(mod->compiled->rpcs[0].input.data);
+    assert_null(mod->compiled->rpcs[0].output.data);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module c {namespace urn:c;prefix c; typedef mytype {type string; units kilometers;}"
+                                        "leaf c1 {type mytype;} leaf c2 {type mytype; units meters;} leaf c3 {type mytype; units meters;}"
+                                        "deviation /c1 {deviate add {units meters;}}"
+                                        "deviation /c2 {deviate delete {units meters;}}"
+                                        "deviation /c3 {deviate replace {units centimeters;}}}", LYS_IN_YANG));
+    assert_non_null(node = mod->compiled->data);
+    assert_string_equal("c1", node->name);
+    assert_string_equal("meters", ((struct lysc_node_leaf*)node)->units);
+    assert_non_null(node = node->next);
+    assert_string_equal("c2", node->name);
+    assert_null(((struct lysc_node_leaf*)node)->units);
+    assert_non_null(node = node->next);
+    assert_string_equal("c3", node->name);
+    assert_string_equal("centimeters", ((struct lysc_node_leaf*)node)->units);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module d {namespace urn:d;prefix d; leaf c1 {type string; must 1;}"
+                                        "container c2 {presence yes; must 1; must 2;} leaf c3 {type string; must 1; must 3;}"
+                                        "deviation /c1 {deviate add {must 3;}}"
+                                        "deviation /c2 {deviate delete {must 2;}}"
+                                        "deviation /c3 {deviate delete {must 3; must 1;}}}", LYS_IN_YANG));
+    assert_non_null(node = mod->compiled->data);
+    assert_string_equal("c1", node->name);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_node_leaf*)node)->musts));
+    assert_string_equal("3", ((struct lysc_node_leaf*)node)->musts[1].cond->expr);
+    assert_non_null(node = node->next);
+    assert_string_equal("c2", node->name);
+    assert_int_equal(1, LY_ARRAY_SIZE(((struct lysc_node_container*)node)->musts));
+    assert_string_equal("1", ((struct lysc_node_container*)node)->musts[0].cond->expr);
+    assert_non_null(node = node->next);
+    assert_string_equal("c3", node->name);
+    assert_null(((struct lysc_node_leaf*)node)->musts);
+
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module e {yang-version 1.1; namespace urn:e;prefix e; typedef mytype {type string; default nothing;}"
+                              "choice a {default a;leaf a {type string;} leaf b {type string;} leaf c {type string; mandatory true;}}"
+                              "choice b {default a;leaf a {type string;} leaf b {type string;}}"
+                              "leaf c {default hello; type string;}"
+                              "leaf-list d {default hello; default world; type string;}"
+                              "leaf c2 {type mytype;} leaf-list d2 {type mytype;}}");
+    assert_non_null(lys_parse_mem(ctx, "module f {yang-version 1.1; namespace urn:f;prefix f;import e {prefix x;}"
+                                  "deviation /x:a {deviate delete {default a;}}"
+                                  "deviation /x:b {deviate delete {default x:a;}}"
+                                  "deviation /x:c {deviate delete {default hello;}}"
+                                  "deviation /x:d {deviate delete {default world;}}}", LYS_IN_YANG));
+    assert_non_null((mod = ly_ctx_get_module_implemented(ctx, "e")));
+    assert_non_null(node = mod->compiled->data);
+    assert_null(((struct lysc_node_choice*)node)->dflt);
+    assert_non_null(node = node->next);
+    assert_null(((struct lysc_node_choice*)node)->dflt);
+    assert_non_null(leaf = (struct lysc_node_leaf*)node->next);
+    assert_null(leaf->dflt);
+    assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+    assert_int_equal(1, LY_ARRAY_SIZE(llist->dflts));
+    assert_string_equal("hello", llist->dflts[0]->realtype->plugin->print(llist->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_non_null(leaf = (struct lysc_node_leaf*)llist->next);
+    assert_string_equal("nothing", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_int_equal(5, leaf->dflt->realtype->refcount); /* 3x type reference, 2x default value reference (typedef's default does not reference own type) */
+    assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+    assert_int_equal(1, LY_ARRAY_SIZE(llist->dflts));
+    assert_string_equal("nothing", llist->dflts[0]->realtype->plugin->print(llist->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+
+    assert_non_null(lys_parse_mem(ctx, "module g {yang-version 1.1; namespace urn:g;prefix g;import e {prefix x;}"
+                                  "deviation /x:b {deviate add {default x:b;}}"
+                                  "deviation /x:c {deviate add {default bye;}}"
+                                  "deviation /x:d {deviate add {default all; default people;}}"
+                                  "deviation /x:c2 {deviate add {default hi; must 1;}}"
+                                  "deviation /x:d2 {deviate add {default hi; default all;}}}", LYS_IN_YANG));
+    assert_non_null((mod = ly_ctx_get_module_implemented(ctx, "e")));
+    assert_non_null(node = mod->compiled->data);
+    assert_null(((struct lysc_node_choice*)node)->dflt);
+    assert_non_null(node = node->next);
+    assert_non_null(((struct lysc_node_choice*)node)->dflt);
+    assert_string_equal("b", ((struct lysc_node_choice*)node)->dflt->name);
+    assert_non_null(leaf = (struct lysc_node_leaf*)node->next);
+    assert_non_null(leaf->dflt);
+    assert_string_equal("bye", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+    assert_int_equal(3, LY_ARRAY_SIZE(llist->dflts));
+    assert_string_equal("hello", llist->dflts[0]->realtype->plugin->print(llist->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_string_equal("all", llist->dflts[1]->realtype->plugin->print(llist->dflts[1], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_string_equal("people", llist->dflts[2]->realtype->plugin->print(llist->dflts[2], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_non_null(leaf = (struct lysc_node_leaf*)llist->next);
+    assert_non_null(leaf->dflt);
+    assert_string_equal("hi", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_int_equal(6, leaf->dflt->realtype->refcount); /* 3x type reference, 3x default value reference
+    - previous type's default values were replaced by node's default values where d2 now has 2 default values */
+    assert_int_equal(1, LY_ARRAY_SIZE(leaf->musts));
+    assert_ptr_equal(leaf->musts[0].module, ly_ctx_get_module_implemented(ctx, "g"));
+    assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+    assert_int_equal(2, LY_ARRAY_SIZE(llist->dflts));
+    assert_string_equal("hi", llist->dflts[0]->realtype->plugin->print(llist->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_string_equal("all", llist->dflts[1]->realtype->plugin->print(llist->dflts[1], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+
+    assert_non_null(lys_parse_mem(ctx, "module h {yang-version 1.1; namespace urn:h;prefix h;import e {prefix x;}"
+                                  "deviation /x:b {deviate replace {default x:a;}}"
+                                  "deviation /x:c {deviate replace {default hello;}}}", LYS_IN_YANG));
+    assert_non_null((mod = ly_ctx_get_module_implemented(ctx, "e")));
+    assert_non_null(node = mod->compiled->data);
+    assert_null(((struct lysc_node_choice*)node)->dflt);
+    assert_non_null(node = node->next);
+    assert_non_null(((struct lysc_node_choice*)node)->dflt);
+    assert_string_equal("a", ((struct lysc_node_choice*)node)->dflt->name);
+    assert_non_null(leaf = (struct lysc_node_leaf*)node->next);
+    assert_non_null(leaf->dflt);
+    assert_string_equal("hello", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+
+    ly_ctx_set_module_imp_clb(ctx, test_imp_clb, "module i {namespace urn:i;prefix i;"
+                              "list l1 {key a; leaf a {type string;} leaf b {type string;} leaf c {type string;}}"
+                              "list l2 {key a; unique \"b c\"; unique \"d\"; leaf a {type string;} leaf b {type string;}"
+                              "         leaf c {type string;} leaf d {type string;}}}");
+    assert_non_null(lys_parse_mem(ctx, "module j {namespace urn:j;prefix j;import i {prefix i;}"
+                                  "augment /i:l1 {leaf j_c {type string;}}"
+                                  "deviation /i:l1 {deviate add {unique \"i:b j_c\"; }}"
+                                  "deviation /i:l1 {deviate add {unique \"i:c\";}}"
+                                  "deviation /i:l2 {deviate delete {unique \"d\"; unique \"b c\";}}}", LYS_IN_YANG));
+    assert_non_null((mod = ly_ctx_get_module_implemented(ctx, "i")));
+    assert_non_null(list = (struct lysc_node_list*)mod->compiled->data);
+    assert_string_equal("l1", list->name);
+    assert_int_equal(2, LY_ARRAY_SIZE(list->uniques));
+    assert_int_equal(2, LY_ARRAY_SIZE(list->uniques[0]));
+    assert_string_equal("b", list->uniques[0][0]->name);
+    assert_string_equal("j_c", list->uniques[0][1]->name);
+    assert_int_equal(1, LY_ARRAY_SIZE(list->uniques[1]));
+    assert_string_equal("c", list->uniques[1][0]->name);
+    assert_non_null(list = (struct lysc_node_list*)list->next);
+    assert_string_equal("l2", list->name);
+    assert_null(list->uniques);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module k {namespace urn:k;prefix k; leaf a {type string;}"
+                                        "container top {leaf x {type string;} leaf y {type string; config false;}}"
+                                        "deviation /a {deviate add {config false; }}"
+                                        "deviation /top {deviate add {config false;}}}", LYS_IN_YANG));
+    assert_non_null(node = mod->compiled->data);
+    assert_string_equal("a", node->name);
+    assert_true(node->flags & LYS_CONFIG_R);
+    assert_non_null(node = node->next);
+    assert_string_equal("top", node->name);
+    assert_true(node->flags & LYS_CONFIG_R);
+    assert_non_null(node = lysc_node_children(node, 0));
+    assert_string_equal("x", node->name);
+    assert_true(node->flags & LYS_CONFIG_R);
+    assert_non_null(node = node->next);
+    assert_string_equal("y", node->name);
+    assert_true(node->flags & LYS_CONFIG_R);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module l {namespace urn:l;prefix l; leaf a {config false; type string;}"
+                                        "container top {config false; leaf x {type string;}}"
+                                        "deviation /a {deviate replace {config true;}}"
+                                        "deviation /top {deviate replace {config true;}}}", LYS_IN_YANG));
+    assert_non_null(node = mod->compiled->data);
+    assert_string_equal("a", node->name);
+    assert_true(node->flags & LYS_CONFIG_W);
+    assert_non_null(node = node->next);
+    assert_string_equal("top", node->name);
+    assert_true(node->flags & LYS_CONFIG_W);
+    assert_non_null(node = lysc_node_children(node, 0));
+    assert_string_equal("x", node->name);
+    assert_true(node->flags & LYS_CONFIG_W);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module m {namespace urn:m;prefix m;"
+                                        "container a {leaf a {type string;}}"
+                                        "container b {leaf b {mandatory true; type string;}}"
+                                        "deviation /a/a {deviate add {mandatory true;}}"
+                                        "deviation /b/b {deviate replace {mandatory false;}}}", LYS_IN_YANG));
+    assert_non_null(node = mod->compiled->data);
+    assert_string_equal("a", node->name);
+    assert_true((node->flags & LYS_MAND_MASK) == LYS_MAND_TRUE);
+    assert_true((lysc_node_children(node, 0)->flags & LYS_MAND_MASK) == LYS_MAND_TRUE);
+    assert_non_null(node = node->next);
+    assert_string_equal("b", node->name);
+    assert_false(node->flags & LYS_MAND_MASK); /* just unset on container */
+    assert_true((lysc_node_children(node, 0)->flags & LYS_MAND_MASK) == LYS_MAND_FALSE);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module n {yang-version 1.1; namespace urn:n;prefix n;"
+                                        "leaf a {default test; type string;}"
+                                        "leaf b {mandatory true; type string;}"
+                                        "deviation /a {deviate add {mandatory true;} deviate delete {default test;}}"
+                                        "deviation /b {deviate add {default test;} deviate replace {mandatory false;}}}", LYS_IN_YANG));
+    assert_non_null(node = mod->compiled->data);
+    assert_string_equal("a", node->name);
+    assert_null(((struct lysc_node_leaf*)node)->dflt);
+    assert_true((node->flags & LYS_MAND_MASK) == LYS_MAND_TRUE);
+    assert_non_null(node = node->next);
+    assert_string_equal("b", node->name);
+    assert_non_null(((struct lysc_node_leaf*)node)->dflt);
+    assert_true((node->flags & LYS_MAND_MASK) == LYS_MAND_FALSE);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module o {namespace urn:o;prefix o;"
+                                        "leaf-list a {type string;}"
+                                        "list b {config false;}"
+                                        "leaf-list c {min-elements 1; max-elements 10; type string;}"
+                                        "list d {min-elements 10; max-elements 100; config false;}"
+                                        "deviation /a {deviate add {min-elements 1; max-elements 10;}}"
+                                        "deviation /b {deviate add {min-elements 10; max-elements 100;}}"
+                                        "deviation /c {deviate replace {min-elements 10; max-elements 100;}}"
+                                        "deviation /d {deviate replace {min-elements 1; max-elements 10;}}}", LYS_IN_YANG));
+    assert_non_null(node = mod->compiled->data);
+    assert_string_equal("a", node->name);
+    assert_int_equal(1, ((struct lysc_node_leaflist*)node)->min);
+    assert_int_equal(10, ((struct lysc_node_leaflist*)node)->max);
+    assert_non_null(node = node->next);
+    assert_string_equal("b", node->name);
+    assert_int_equal(10, ((struct lysc_node_list*)node)->min);
+    assert_int_equal(100, ((struct lysc_node_list*)node)->max);
+    assert_non_null(node = node->next);
+    assert_string_equal("c", node->name);
+    assert_int_equal(10, ((struct lysc_node_leaflist*)node)->min);
+    assert_int_equal(100, ((struct lysc_node_leaflist*)node)->max);
+    assert_non_null(node = node->next);
+    assert_string_equal("d", node->name);
+    assert_int_equal(1, ((struct lysc_node_list*)node)->min);
+    assert_int_equal(10, ((struct lysc_node_list*)node)->max);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module p {yang-version 1.1; namespace urn:p;prefix p; typedef mytype {type int8; default 1;}"
+                                        "leaf a {type string; default 10;} leaf-list b {type string;}"
+                                        "deviation /a {deviate replace {type mytype;}}"
+                                        "deviation /b {deviate replace {type mytype;}}}", LYS_IN_YANG));
+    assert_non_null(leaf = (struct lysc_node_leaf*)mod->compiled->data);
+    assert_string_equal("a", leaf->name);
+    assert_int_equal(LY_TYPE_INT8, leaf->type->basetype);
+    assert_string_equal("10", leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_int_equal(10, leaf->dflt->uint8);
+    assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+    assert_string_equal("b", llist->name);
+    assert_int_equal(LY_TYPE_INT8, llist->type->basetype);
+    assert_int_equal(1, LY_ARRAY_SIZE(llist->dflts));
+    assert_string_equal("1", llist->dflts[0]->realtype->plugin->print(llist->dflts[0], LYD_XML, NULL, NULL, &dynamic));
+    assert_int_equal(0, dynamic);
+    assert_int_equal(1, llist->dflts[0]->uint8);
+
+    /* instance-identifiers with NULL canonical_cach are changed to string types with a canonical_cache value equal to the original value */
+    assert_non_null(mod = lys_parse_mem(ctx, "module q {yang-version 1.1; namespace urn:q;prefix q; import e {prefix e;}"
+                                        "leaf q {type instance-identifier; default \"/e:d2\";}"
+                                        "leaf-list ql {type instance-identifier; default \"/e:d\"; default \"/e:d2\";}}", LYS_IN_YANG));
+    assert_non_null(lys_parse_mem(ctx, "module qdev {yang-version 1.1; namespace urn:qdev;prefix qd; import q {prefix q;}"
+                                  "deviation /q:q { deviate replace {type string;}}"
+                                  "deviation /q:ql { deviate replace {type string;}}}", LYS_IN_YANG));
+    assert_non_null(leaf = (struct lysc_node_leaf*)mod->compiled->data);
+    assert_int_equal(LY_TYPE_STRING, leaf->dflt->realtype->basetype);
+    assert_non_null(leaf->dflt->canonical_cache);
+    assert_string_equal("/e:d2", leaf->dflt->canonical_cache);
+    assert_non_null(llist = (struct lysc_node_leaflist*)leaf->next);
+    assert_int_equal(2, LY_ARRAY_SIZE(llist->dflts));
+    assert_int_equal(2, LY_ARRAY_SIZE(llist->dflts_mods));
+    assert_ptr_equal(llist->dflts_mods[0], mod);
+    assert_int_equal(LY_TYPE_STRING, llist->dflts[0]->realtype->basetype);
+    assert_string_equal("/e:d", llist->dflts[0]->canonical_cache);
+    assert_ptr_equal(llist->dflts_mods[1], mod);
+    assert_int_equal(LY_TYPE_STRING, llist->dflts[0]->realtype->basetype);
+    assert_string_equal("/e:d2", llist->dflts[1]->canonical_cache);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module r {yang-version 1.1; namespace urn:r;prefix r;"
+                                        "typedef mytype {type uint8; default 200;}"
+                                        "leaf r {type mytype;} leaf-list lr {type mytype;}"
+                                        "deviation /r:r {deviate replace {type string;}}"
+                                        "deviation /r:lr {deviate replace {type string;}}}", LYS_IN_YANG));
+    assert_non_null(leaf = (struct lysc_node_leaf*)mod->compiled->data);
+    assert_string_equal("r", leaf->name);
+    assert_null(leaf->dflt);
+    assert_null(leaf->dflt_mod);
+    assert_non_null(llist = (struct lysc_node_leaflist* )leaf->next);
+    assert_string_equal("lr", llist->name);
+    assert_null(llist->dflts);
+    assert_null(llist->dflts_mods);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module s {yang-version 1.1; namespace urn:s;prefix s;"
+                                        "leaf s {type instance-identifier {require-instance true;} default /s:x;}"
+                                        "leaf x {type string;} leaf y {type string;}"
+                                        "deviation /s:s {deviate replace {default /s:y;}}}", LYS_IN_YANG));
+    assert_non_null(leaf = (struct lysc_node_leaf*)mod->compiled->data);
+    assert_string_equal("s", leaf->name);
+    assert_non_null(leaf->dflt);
+    assert_non_null(str = leaf->dflt->realtype->plugin->print(leaf->dflt, LYD_XML, lys_get_prefix, mod, &dynamic));
+    assert_string_equal("/s:y", str);
+    if (dynamic) { free((char*)str); }
+
+    assert_null(lys_parse_mem(ctx, "module aa1 {namespace urn:aa1;prefix aa1;import a {prefix a;}"
+                              "deviation /a:top/a:z {deviate not-supported;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid absolute-schema-nodeid value \"/a:top/a:z\" - target node not found. /aa1:{deviation='/a:top/a:z'}");
+    assert_non_null(lys_parse_mem(ctx, "module aa2 {namespace urn:aa2;prefix aa2;import a {prefix a;}"
+                              "deviation /a:top/a:a {deviate not-supported;}"
+                              "deviation /a:top/a:a {deviate add {default error;}}}", LYS_IN_YANG));
+    /* warning */
+    logbuf_assert("Useless multiple (2) deviates on node \"/a:top/a:a\" since the node is not-supported.");
+
+    assert_null(lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb;import a {prefix a;}"
+                              "deviation a:top/a:a {deviate not-supported;}}", LYS_IN_YANG));
+    logbuf_assert("Invalid absolute-schema-nodeid value \"a:top/a:a\" - missing starting \"/\". /bb:{deviation='a:top/a:a'}");
+
+    assert_null(lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc; container c;"
+                              "deviation /c {deviate add {units meters;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of container node - it is not possible to add \"units\" property. /cc:{deviation='/c'}");
+    assert_null(lys_parse_mem(ctx, "module cd {namespace urn:cd;prefix cd; leaf c {type string; units centimeters;}"
+                              "deviation /c {deviate add {units meters;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation adding \"units\" property which already exists (with value \"centimeters\"). /cd:{deviation='/c'}");
+
+    assert_null(lys_parse_mem(ctx, "module dd1 {namespace urn:dd1;prefix dd1; container c;"
+                              "deviation /c {deviate delete {units meters;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of container node - it is not possible to delete \"units\" property. /dd1:{deviation='/c'}");
+    assert_null(lys_parse_mem(ctx, "module dd2 {namespace urn:dd2;prefix dd2; leaf c {type string;}"
+                              "deviation /c {deviate delete {units meters;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation deleting \"units\" property \"meters\" which is not present. /dd2:{deviation='/c'}");
+    assert_null(lys_parse_mem(ctx, "module dd3 {namespace urn:dd3;prefix dd3; leaf c {type string; units centimeters;}"
+                              "deviation /c {deviate delete {units meters;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation deleting \"units\" property \"meters\" which does not match the target's property value \"centimeters\"."
+            " /dd3:{deviation='/c'}");
+
+    assert_null(lys_parse_mem(ctx, "module ee1 {namespace urn:ee1;prefix ee1; container c;"
+                              "deviation /c {deviate replace {units meters;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of container node - it is not possible to replace \"units\" property. /ee1:{deviation='/c'}");
+    assert_null(lys_parse_mem(ctx, "module ee2 {namespace urn:ee2;prefix ee2; leaf c {type string;}"
+                              "deviation /c {deviate replace {units meters;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation replacing \"units\" property \"meters\" which is not present. /ee2:{deviation='/c'}");
+
+    /* the default is already deleted in /e:a byt module f */
+    assert_null(lys_parse_mem(ctx, "module ff1 {namespace urn:ff1;prefix ff1; import e {prefix e;}"
+                              "deviation /e:a {deviate delete {default x:a;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation deleting \"default\" property \"x:a\" which is not present. /ff1:{deviation='/e:a'}");
+    assert_null(lys_parse_mem(ctx, "module ff2 {namespace urn:ff2;prefix ff2; import e {prefix e;}"
+                              "deviation /e:b {deviate delete {default x:a;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation deleting \"default\" property \"x:a\" of choice. "
+                  "The prefix does not match any imported module of the deviation module. /ff2:{deviation='/e:b'}");
+    assert_null(lys_parse_mem(ctx, "module ff3 {namespace urn:ff3;prefix ff3; import e {prefix e;}"
+                              "deviation /e:b {deviate delete {default e:b;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation deleting \"default\" property \"e:b\" of choice does not match the default case name \"a\". /ff3:{deviation='/e:b'}");
+    assert_null(lys_parse_mem(ctx, "module ff4 {namespace urn:ff4;prefix ff4; import e {prefix e;}"
+                              "deviation /e:b {deviate delete {default ff4:a;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation deleting \"default\" property \"ff4:a\" of choice. The prefix does not match the default case's module. /ff4:{deviation='/e:b'}");
+    assert_null(lys_parse_mem(ctx, "module ff5 {namespace urn:ff5;prefix ff5; anyxml a;"
+                              "deviation /a {deviate delete {default x;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of anyxml node - it is not possible to delete \"default\" property. /ff5:{deviation='/a'}");
+    assert_null(lys_parse_mem(ctx, "module ff6 {namespace urn:ff6;prefix ff6; import e {prefix e;}"
+                              "deviation /e:c {deviate delete {default hi;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation deleting \"default\" property \"hi\" which does not match the target's property value \"hello\". /ff6:{deviation='/e:c'}");
+    assert_null(lys_parse_mem(ctx, "module ff7 {namespace urn:ff7;prefix ff7; import e {prefix e;}"
+                              "deviation /e:d {deviate delete {default hi;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation deleting \"default\" property \"hi\" which does not match any of the target's property values. /ff7:{deviation='/e:d'}");
+
+    assert_null(lys_parse_mem(ctx, "module gg1 {namespace urn:gg1;prefix gg1; import e {prefix e;}"
+                              "deviation /e:b {deviate add {default e:a;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation adding \"default\" property which already exists (with value \"a\"). /gg1:{deviation='/e:b'}");
+    assert_null(lys_parse_mem(ctx, "module gg2 {namespace urn:gg2;prefix gg2; import e {prefix e;}"
+                              "deviation /e:a {deviate add {default x:a;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation adding \"default\" property \"x:a\" of choice. "
+                  "The prefix does not match any imported module of the deviation module. /gg2:{deviation='/e:a'}");
+    assert_null(lys_parse_mem(ctx, "module gg3 {namespace urn:gg3;prefix gg3; import e {prefix e;}"
+                              "deviation /e:a {deviate add {default a;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation adding \"default\" property \"a\" of choice - the specified case does not exists. /gg3:{deviation='/e:a'}");
+    assert_null(lys_parse_mem(ctx, "module gg4 {namespace urn:gg4;prefix gg4; import e {prefix e;}"
+                              "deviation /e:c {deviate add {default hi;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation adding \"default\" property which already exists (with value \"hello\"). /gg4:{deviation='/e:c'}");
+    assert_null(lys_parse_mem(ctx, "module gg4 {namespace urn:gg4;prefix gg4; import e {prefix e;}"
+                              "deviation /e:a {deviate add {default e:c;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation adding \"default\" property \"e:c\" of choice - mandatory node \"c\" under the default case. /gg4:{deviation='/e:a'}");
+    assert_null(lys_parse_mem(ctx, "module gg5 {namespace urn:gg5;prefix gg5; leaf x {type string; mandatory true;}"
+                              "deviation /x {deviate add {default error;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation combining default value and mandatory leaf. /gg5:{deviation='/x'}");
+
+    assert_null(lys_parse_mem(ctx, "module hh1 {yang-version 1.1; namespace urn:hh1;prefix hh1; import e {prefix e;}"
+                              "deviation /e:d {deviate replace {default hi;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of leaf-list node - it is not possible to replace \"default\" property. /hh1:{deviation='/e:d'}");
+
+    assert_null(lys_parse_mem(ctx, "module ii1 {namespace urn:ii1;prefix ii1; import i {prefix i;}"
+                              "deviation /i:l1 {deviate delete {unique x;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation deleting \"unique\" property \"x\" which does not match any of the target's property values. /ii1:{deviation='/i:l1'}");
+    assert_null(lys_parse_mem(ctx, "module ii2 {namespace urn:ii2;prefix ii2; import i {prefix i;} leaf x { type string;}"
+                              "deviation /i:l2 {deviate delete {unique d;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation deleting \"unique\" property \"d\" which does not match any of the target's property values. /ii2:{deviation='/i:l2'}");
+    assert_null(lys_parse_mem(ctx, "module ii3 {namespace urn:ii3;prefix ii3; leaf x { type string;}"
+                              "deviation /x {deviate delete {unique d;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of leaf node - it is not possible to delete \"unique\" property. /ii3:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module ii4 {namespace urn:ii4;prefix ii4; leaf x { type string;}"
+                              "deviation /x {deviate add {unique d;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of leaf node - it is not possible to add \"unique\" property. /ii4:{deviation='/x'}");
+
+    assert_null(lys_parse_mem(ctx, "module jj1 {namespace urn:jj1;prefix jj1; choice ch {case a {leaf a{type string;}}}"
+                              "deviation /ch/a {deviate add {config false;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of case node - it is not possible to add \"config\" property. /jj1:{deviation='/ch/a'}");
+    assert_null(lys_parse_mem(ctx, "module jj2 {namespace urn:jj2;prefix jj2; container top {config false; leaf x {type string;}}"
+                              "deviation /top/x {deviate add {config true;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of config - configuration node cannot be child of any state data node. /jj2:{deviation='/top/x'}");
+    assert_null(lys_parse_mem(ctx, "module jj3 {namespace urn:jj3;prefix jj3; container top {leaf x {type string;}}"
+                              "deviation /top/x {deviate replace {config false;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation replacing \"config\" property \"config false\" which is not present. /jj3:{deviation='/top/x'}");
+    assert_null(lys_parse_mem(ctx, "module jj4 {namespace urn:jj4;prefix jj4; choice ch {case a {leaf a{type string;}}}"
+                              "deviation /ch/a {deviate replace {config false;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of case node - it is not possible to replace \"config\" property. /jj4:{deviation='/ch/a'}");
+    assert_null(lys_parse_mem(ctx, "module jj5 {namespace urn:jj5;prefix jj5; container top {leaf x {type string; config true;}}"
+                              "deviation /top {deviate add {config false;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of config - configuration node cannot be child of any state data node. /jj5:{deviation='/top'}");
+    assert_null(lys_parse_mem(ctx, "module jj6 {namespace urn:jj6;prefix jj6; leaf x {config false; type string;}"
+                              "deviation /x {deviate add {config true;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation adding \"config\" property which already exists (with value \"config false\"). /jj6:{deviation='/x'}");
+
+    assert_null(lys_parse_mem(ctx, "module kk1 {namespace urn:kk1;prefix kk1; container top {leaf a{type string;}}"
+                              "deviation /top {deviate add {mandatory true;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of mandatory - container cannot hold mandatory statement. /kk1:{deviation='/top'}");
+    assert_null(lys_parse_mem(ctx, "module kk2 {namespace urn:kk2;prefix kk2; container top {leaf a{type string;}}"
+                              "deviation /top {deviate replace {mandatory true;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation replacing \"mandatory\" property \"mandatory true\" which is not present. /kk2:{deviation='/top'}");
+    assert_null(lys_parse_mem(ctx, "module kk3 {namespace urn:kk3;prefix kk3; container top {leaf x {type string;}}"
+                              "deviation /top/x {deviate replace {mandatory true;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation replacing \"mandatory\" property \"mandatory true\" which is not present. /kk3:{deviation='/top/x'}");
+    assert_null(lys_parse_mem(ctx, "module kk4 {namespace urn:kk4;prefix kk4; leaf x {mandatory true; type string;}"
+                              "deviation /x {deviate add {mandatory false;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation adding \"mandatory\" property which already exists (with value \"mandatory true\"). /kk4:{deviation='/x'}");
+
+    assert_null(lys_parse_mem(ctx, "module ll1 {namespace urn:ll1;prefix ll1; leaf x {default test; type string;}"
+                              "deviation /x {deviate add {mandatory true;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation combining default value and mandatory leaf. /ll1:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module ll2 {yang-version 1.1; namespace urn:ll2;prefix ll2; leaf-list x {default test; type string;}"
+                              "deviation /x {deviate add {min-elements 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation combining default value and mandatory leaf-list. /ll2:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module ll2 {namespace urn:ll2;prefix ll2; choice ch {default a; leaf a {type string;} leaf b {type string;}}"
+                              "deviation /ch {deviate add {mandatory true;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation combining default case and mandatory choice. /ll2:{deviation='/ch'}");
+
+    assert_null(lys_parse_mem(ctx, "module mm1 {namespace urn:mm1;prefix mm1; leaf-list x {min-elements 10; type string;}"
+                              "deviation /x {deviate add {max-elements 5;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid combination of min-elements and max-elements after deviation: min value 10 is bigger than max value 5. /mm1:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module mm2 {namespace urn:mm2;prefix mm2; leaf-list x {max-elements 10; type string;}"
+                              "deviation /x {deviate add {min-elements 20;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid combination of min-elements and max-elements after deviation: min value 20 is bigger than max value 10. /mm2:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module mm3 {namespace urn:mm3;prefix mm3; list x {min-elements 5; max-elements 10; config false;}"
+                              "deviation /x {deviate replace {max-elements 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid combination of min-elements and max-elements after deviation: min value 5 is bigger than max value 1. /mm3:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module mm4 {namespace urn:mm4;prefix mm4; list x {min-elements 5; max-elements 10; config false;}"
+                              "deviation /x {deviate replace {min-elements 20;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid combination of min-elements and max-elements after deviation: min value 20 is bigger than max value 10. /mm4:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module mm5 {namespace urn:mm5;prefix mm5; leaf-list x {type string; min-elements 5;}"
+                              "deviation /x {deviate add {min-elements 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation adding \"min-elements\" property which already exists (with value \"5\"). /mm5:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module mm6 {namespace urn:mm6;prefix mm6; list x {config false; min-elements 5;}"
+                              "deviation /x {deviate add {min-elements 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation adding \"min-elements\" property which already exists (with value \"5\"). /mm6:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module mm7 {namespace urn:mm7;prefix mm7; leaf-list x {type string; max-elements 5;}"
+                              "deviation /x {deviate add {max-elements 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation adding \"max-elements\" property which already exists (with value \"5\"). /mm7:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module mm8 {namespace urn:mm8;prefix mm8; list x {config false; max-elements 5;}"
+                              "deviation /x {deviate add {max-elements 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation adding \"max-elements\" property which already exists (with value \"5\"). /mm8:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module mm9 {namespace urn:mm9;prefix mm9; leaf-list x {type string;}"
+                              "deviation /x {deviate replace {min-elements 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation replacing with \"min-elements\" property \"1\" which is not present. /mm9:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module mm10 {namespace urn:mm10;prefix mm10; list x {config false;}"
+                              "deviation /x {deviate replace {min-elements 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation replacing with \"min-elements\" property \"1\" which is not present. /mm10:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module mm11 {namespace urn:mm11;prefix mm11; leaf-list x {type string;}"
+                              "deviation /x {deviate replace {max-elements 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation replacing with \"max-elements\" property \"1\" which is not present. /mm11:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module mm12 {namespace urn:mm12;prefix mm12; list x {config false; }"
+                              "deviation /x {deviate replace {max-elements 1;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation replacing with \"max-elements\" property \"1\" which is not present. /mm12:{deviation='/x'}");
+
+    assert_null(lys_parse_mem(ctx, "module nn1 {namespace urn:nn1;prefix nn1; anyxml x;"
+                              "deviation /x {deviate replace {type string;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation of anyxml node - it is not possible to replace \"type\" property. /nn1:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module nn2 {namespace urn:nn2;prefix nn2; leaf-list x {type string;}"
+                              "deviation /x {deviate replace {type empty;}}}", LYS_IN_YANG));
+    logbuf_assert("Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules. /nn2:{deviation='/x'}");
+
+    assert_null(lys_parse_mem(ctx, "module oo1 {namespace urn:oo1;prefix oo1; leaf x {type uint16; default 300;}"
+                                  "deviation /x {deviate replace {type uint8;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation replacing leaf's type - the leaf's default value \"300\" does not match the type "
+                  "(Value \"300\" is out of uint8's min/max bounds.). /oo1:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module oo2 {yang-version 1.1;namespace urn:oo2;prefix oo2; leaf-list x {type uint16; default 10; default 300;}"
+                                  "deviation /x {deviate replace {type uint8;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation replacing leaf-list's type - the leaf-list's default value \"300\" does not match the type "
+                  "(Value \"300\" is out of uint8's min/max bounds.). /oo2:{deviation='/x'}");
+    assert_null(lys_parse_mem(ctx, "module oo3 {namespace urn:oo3;prefix oo3; leaf x {type uint8;}"
+                                  "deviation /x {deviate add {default 300;}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid deviation setting \"default\" property \"300\" which does not fit the type "
+                  "(Value \"300\" is out of uint8's min/max bounds.). /oo3:{deviation='/x'}");
+
+/* TODO recompiling reference object after deviation changes schema tree
+    assert_non_null(lys_parse_mem(ctx, "module pp {namespace urn:pp;prefix pp; leaf l { type leafref {path /c/x;}}"
+                                  "container c {leaf x {type string;} leaf y {type string;}}}", LYS_IN_YANG));
+    assert_null(lys_parse_mem(ctx, "module pp1 {namespace urn:pp1;prefix pp1; import pp {prefix pp;}"
+                              "deviation /pp:c/pp:x {deviate not-supported;}}", LYS_IN_YANG));
+    logbuf_assert("???. /pp:l}");
+*/
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+static void
+test_when(void **state)
+{
+    *state = test_when;
+
+    struct ly_ctx *ctx;
+
+    assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, LY_CTX_DISABLE_SEARCHDIRS, &ctx));
+
+    assert_null(lys_parse_mem(ctx,
+        "module a {"
+            "namespace urn:a;"
+            "prefix a;"
+            "container cont {"
+                "leaf l {"
+                    "when \"/cont/lst[val='25']\";"
+                    "type empty;"
+                "}"
+                "list lst {"
+                    "key \"k\";"
+                    "leaf k {"
+                        "type uint8;"
+                    "}"
+                    "leaf val {"
+                        "when /cont2;"
+                        "type int32;"
+                    "}"
+                "}"
+            "}"
+            "container cont2 {"
+                "presence \"a\";"
+                "when ../cont/l;"
+            "}"
+        "}"
+    , LYS_IN_YANG));
+    logbuf_assert("When condition of \"cont2\" includes a self-reference (referenced by when of \"l\"). /a:cont2");
+
+    assert_null(lys_parse_mem(ctx,
+        "module a {"
+            "namespace urn:a;"
+            "prefix a;"
+            "container cont {"
+                "leaf l {"
+                    "when \"/cont/lst[val='25']\";"
+                    "type empty;"
+                "}"
+                "list lst {"
+                    "key \"k\";"
+                    "leaf k {"
+                        "type uint8;"
+                    "}"
+                    "leaf val {"
+                        "when /cont2;"
+                        "type int32;"
+                    "}"
+                "}"
+            "}"
+            "container cont2 {"
+                "presence \"a\";"
+                "when ../cont/lst/val;"
+            "}"
+        "}"
+    , LYS_IN_YANG));
+    logbuf_assert("When condition of \"cont2\" includes a self-reference (referenced by when of \"val\"). /a:cont2");
+
+    assert_null(lys_parse_mem(ctx,
+        "module a {"
+            "namespace urn:a;"
+            "prefix a;"
+            "leaf val {"
+                "type int64;"
+                "when \"../val='25'\";"
+            "}"
+        "}"
+    , LYS_IN_YANG));
+    logbuf_assert("When condition of \"val\" is accessing its own conditional node. /a:val");
+
+    assert_null(lys_parse_mem(ctx,
+        "module a {"
+            "namespace urn:a;"
+            "prefix a;"
+            "grouping grp {"
+                "leaf val {"
+                    "type int64;"
+                "}"
+            "}"
+            "uses grp {"
+                "when \"val='25'\";"
+            "}"
+        "}"
+    , LYS_IN_YANG));
+    logbuf_assert("When condition of \"val\" is accessing its own conditional node. /a:val");
+
+    assert_null(lys_parse_mem(ctx,
+        "module a {"
+            "namespace urn:a;"
+            "prefix a;"
+            "augment /cont {"
+                "when \"val='25'\";"
+                "leaf val {"
+                    "type int64;"
+                "}"
+            "}"
+            "container cont;"
+        "}"
+    , LYS_IN_YANG));
+    logbuf_assert("When condition of \"val\" is accessing its own conditional node. /a:cont/val");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
+int main(void)
+{
+    const struct CMUnitTest tests[] = {
+        cmocka_unit_test_setup_teardown(test_module, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_type_length, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_type_range, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_type_pattern, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_type_enum, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_type_bits, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_type_dec64, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_type_instanceid, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_type_identityref, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_type_leafref, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_type_empty, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_type_union, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_type_dflt, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_status, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_node_container, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_node_leaflist, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_node_list, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_node_choice, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_node_anydata, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_action, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_notification, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_grouping, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_uses, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_refine, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_augment, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_deviation, logger_setup, logger_teardown),
+        cmocka_unit_test_setup_teardown(test_when, logger_setup, logger_teardown),
+    };
+
+    return cmocka_run_group_tests(tests, NULL, NULL);
+}