schema compile CHANGE support for enumeration and bits types
diff --git a/tests/src/test_tree_schema_compile.c b/tests/src/test_tree_schema_compile.c
index f23b541..20c98b5 100644
--- a/tests/src/test_tree_schema_compile.c
+++ b/tests/src/test_tree_schema_compile.c
@@ -782,6 +782,198 @@
     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 {namespace urn:a;prefix a;feature f; leaf l {type enumeration {"
+                                        "enum automin; enum min {value -2147483648;}enum one {if-feature f; value 1;}"
+                                        "enum two; enum seven {value 7;}enum eight;}}}", LYS_IN_YANG));
+    assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_ENUM, type->basetype);
+    assert_non_null(((struct lysc_type_enum*)type)->enums);
+    assert_int_equal(6, LY_ARRAY_SIZE(((struct lysc_type_enum*)type)->enums));
+    assert_non_null(((struct lysc_type_enum*)type)->enums[2].iffeatures);
+    assert_string_equal("automin", ((struct lysc_type_enum*)type)->enums[0].name);
+    assert_int_equal(0, ((struct lysc_type_enum*)type)->enums[0].value);
+    assert_string_equal("min", ((struct lysc_type_enum*)type)->enums[1].name);
+    assert_int_equal(-2147483648, ((struct lysc_type_enum*)type)->enums[1].value);
+    assert_string_equal("one", ((struct lysc_type_enum*)type)->enums[2].name);
+    assert_int_equal(1, ((struct lysc_type_enum*)type)->enums[2].value);
+    assert_string_equal("two", ((struct lysc_type_enum*)type)->enums[3].name);
+    assert_int_equal(2, ((struct lysc_type_enum*)type)->enums[3].value);
+    assert_string_equal("seven", ((struct lysc_type_enum*)type)->enums[4].name);
+    assert_int_equal(7, ((struct lysc_type_enum*)type)->enums[4].value);
+    assert_string_equal("eight", ((struct lysc_type_enum*)type)->enums[5].name);
+    assert_int_equal(8, ((struct lysc_type_enum*)type)->enums[5].value);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;feature f; typedef mytype {type enumeration {"
+                                        "enum 11; enum min {value -2147483648;}enum x$& {if-feature f; value 1;}"
+                                        "enum two; enum seven {value 7;}enum eight;}} leaf l { type mytype {enum seven;enum eight;}}}",
+                                        LYS_IN_YANG));
+    assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_ENUM, type->basetype);
+    assert_non_null(((struct lysc_type_enum*)type)->enums);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_enum*)type)->enums));
+    assert_string_equal("seven", ((struct lysc_type_enum*)type)->enums[0].name);
+    assert_int_equal(7, ((struct lysc_type_enum*)type)->enums[0].value);
+    assert_string_equal("eight", ((struct lysc_type_enum*)type)->enums[1].name);
+    assert_int_equal(8, ((struct lysc_type_enum*)type)->enums[1].value);
+
+
+    /* invalid cases */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                   "enum one {value -2147483649;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid value \"-2147483649\" of \"value\". Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                   "enum one {value 2147483648;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid value \"2147483648\" of \"value\". Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                   "enum one; enum one;}}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"one\" of enum statement. Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                   "enum '';}}}", LYS_IN_YANG));
+    logbuf_assert("Enum name must not be zero-length. Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                   "enum ' x';}}}", LYS_IN_YANG));
+    logbuf_assert("Enum name must not have any leading or trailing whitespaces (\" x\"). Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                   "enum 'x ';}}}", LYS_IN_YANG));
+    logbuf_assert("Enum name must not have any leading or trailing whitespaces (\"x \"). Line number 1.");
+    assert_non_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type enumeration {"
+                                  "enum 'inva\nlid';}}}", LYS_IN_YANG));
+    logbuf_assert("Control characters in enum name should be avoided (\"inva\nlid\", character number 5).");
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; leaf l {type enumeration;}}", LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+    logbuf_assert("Missing enum substatement for enumeration type.");
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;typedef mytype {type enumeration {enum one;}}"
+                                             "leaf l {type mytype {enum two;}}}", LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+    logbuf_assert("Invalid enumeration - derived type adds new item \"two\".");
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;typedef mytype {type enumeration {enum one;}}"
+                                             "leaf l {type mytype {enum one {value 1;}}}}", LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+    logbuf_assert("Invalid enumeration - value of the item \"one\" has changed from 0 to 1 in the derived type.");
+    assert_non_null(mod = lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;leaf l {type enumeration {enum x {value 2147483647;}enum y;}}}",
+                                        LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+    logbuf_assert("Invalid enumeration - it is not possible to auto-assign enum value for \"y\" since the highest value is already 2147483647.");
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;leaf l {type enumeration {enum x {value 1;}enum y {value 1;}}}}",
+                                        LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+    logbuf_assert("Invalid enumeration - value 1 collide in items \"y\" and \"x\".");
+
+    *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 {namespace urn:a;prefix a;feature f; leaf l {type bits {"
+                                        "bit automin; bit one {if-feature f; position 1;}"
+                                        "bit two; bit seven {position 7;}bit eight;}}}", LYS_IN_YANG));
+    assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_BITS, type->basetype);
+    assert_non_null(((struct lysc_type_bits*)type)->bits);
+    assert_int_equal(5, LY_ARRAY_SIZE(((struct lysc_type_bits*)type)->bits));
+    assert_non_null(((struct lysc_type_bits*)type)->bits[1].iffeatures);
+    assert_string_equal("automin", ((struct lysc_type_bits*)type)->bits[0].name);
+    assert_int_equal(0, ((struct lysc_type_bits*)type)->bits[0].position);
+    assert_string_equal("one", ((struct lysc_type_bits*)type)->bits[1].name);
+    assert_int_equal(1, ((struct lysc_type_bits*)type)->bits[1].position);
+    assert_string_equal("two", ((struct lysc_type_bits*)type)->bits[2].name);
+    assert_int_equal(2, ((struct lysc_type_bits*)type)->bits[2].position);
+    assert_string_equal("seven", ((struct lysc_type_bits*)type)->bits[3].name);
+    assert_int_equal(7, ((struct lysc_type_bits*)type)->bits[3].position);
+    assert_string_equal("eight", ((struct lysc_type_bits*)type)->bits[4].name);
+    assert_int_equal(8, ((struct lysc_type_bits*)type)->bits[4].position);
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module b {namespace urn:b;prefix b;feature f; typedef mytype {type bits {"
+                                        "bit automin; bit one {if-feature f; value 1;}"
+                                        "bit two; bit seven {value 7;}bit eight;}} leaf l { type mytype {bit seven;bit eight;}}}",
+                                        LYS_IN_YANG));
+    assert_int_equal(LY_SUCCESS, lys_compile(mod, 0));
+    type = ((struct lysc_node_leaf*)mod->compiled->data)->type;
+    assert_non_null(type);
+    assert_int_equal(LY_TYPE_BITS, type->basetype);
+    assert_non_null(((struct lysc_type_bits*)type)->bits);
+    assert_int_equal(2, LY_ARRAY_SIZE(((struct lysc_type_bits*)type)->bits));
+    assert_string_equal("seven", ((struct lysc_type_bits*)type)->bits[0].name);
+    assert_int_equal(7, ((struct lysc_type_bits*)type)->bits[0].position);
+    assert_string_equal("eight", ((struct lysc_type_bits*)type)->bits[1].name);
+    assert_int_equal(8, ((struct lysc_type_bits*)type)->bits[1].position);
+
+
+    /* invalid cases */
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+                                   "bit one {position -1;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid value \"-1\" of \"position\". Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+                                   "bit one {value 4294967296;}}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid value \"4294967296\" of \"value\". Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+                                   "bit one; bit one;}}}", LYS_IN_YANG));
+    logbuf_assert("Duplicate identifier \"one\" of bit statement. Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+                                   "bit '11';}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid identifier first character '1'. Line number 1.");
+    assert_null(lys_parse_mem(ctx, "module aa {namespace urn:aa;prefix aa; leaf l {type bits {"
+                                   "bit 'x1$1';}}}", LYS_IN_YANG));
+    logbuf_assert("Invalid identifier character '$'. Line number 1.");
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module bb {namespace urn:bb;prefix bb; leaf l {type bits;}}", LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+    logbuf_assert("Missing bit substatement for bits type.");
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module cc {namespace urn:cc;prefix cc;typedef mytype {type bits {bit one;}}"
+                                             "leaf l {type mytype {bit two;}}}", LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+    logbuf_assert("Invalid bits - derived type adds new item \"two\".");
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module dd {namespace urn:dd;prefix dd;typedef mytype {type bits {bit one;}}"
+                                             "leaf l {type mytype {bit one {position 1;}}}}", LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+    logbuf_assert("Invalid bits - position of the item \"one\" has changed from 0 to 1 in the derived type.");
+    assert_non_null(mod = lys_parse_mem(ctx, "module ee {namespace urn:ee;prefix ee;leaf l {type bits {bit x {position 4294967295;}bit y;}}}",
+                                        LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+    logbuf_assert("Invalid bits - it is not possible to auto-assign bit position for \"y\" since the highest value is already 4294967295.");
+
+    assert_non_null(mod = lys_parse_mem(ctx, "module ff {namespace urn:ff;prefix ff;leaf l {type bits {bit x {value 1;}bit y {value 1;}}}}",
+                                        LYS_IN_YANG));
+    assert_int_equal(LY_EVALID, lys_compile(mod, 0));
+    logbuf_assert("Invalid bits - position 1 collide in items \"y\" and \"x\".");
+
+    *state = NULL;
+    ly_ctx_destroy(ctx, NULL);
+}
+
 int main(void)
 {
     const struct CMUnitTest tests[] = {
@@ -791,6 +983,8 @@
         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_node_container, logger_setup, logger_teardown),
     };