test ADD conformance test section 9.4.4
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 56bca3d..87a30e3 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -4,7 +4,7 @@
 set(data_tests test_data_initialization test_leafref_remove test_instid_remove test_keys test_autodel test_when test_defaults test_emptycont test_unique test_mandatory test_json test_parse_print)
 set(schema_yin_tests test_print_transform)
 set(schema_tests test_ietf test_augment test_typedef test_import test_include)
-set(conformance_tests test_sec6_1_1 test_sec6_2 test_sec5_1 test_sec5_5 test_sec6_1_3 test_sec6_2_1 test_sec7_1 test_sec7_2 test_sec7_3 test_sec7_3_1 test_sec7_3_4 test_sec7_5_2 test_sec7_5_4 test_sec7_5_5 test_sec7_6_2 test_sec7_6_3 test_sec7_6_5 test_sec7_7_2 test_sec7_7_3 test_sec7_7_4 test_sec7_7_5 test_sec7_8_1 test_sec7_8_2 test_sec7_8_3 test_sec7_9_1 test_sec7_9_2 test_sec7_9_3 test_sec7_9_4 test_sec7_10 test_sec7_11 test_sec7_12_1 test_sec7_12_2 test_sec7_13_1 test_sec7_13_2 test_sec7_15 test_sec7_16_1 test_sec7_16_2 test_sec7_18_1 test_sec7_18_2 test_sec7_18_3_1 test_sec7_18_3_2 test_sec7_19_1 test_sec7_19_5 test_sec9_2)
+set(conformance_tests test_sec6_1_1 test_sec6_2 test_sec5_1 test_sec5_5 test_sec6_1_3 test_sec6_2_1 test_sec7_1 test_sec7_2 test_sec7_3 test_sec7_3_1 test_sec7_3_4 test_sec7_5_2 test_sec7_5_4 test_sec7_5_5 test_sec7_6_2 test_sec7_6_3 test_sec7_6_5 test_sec7_7_2 test_sec7_7_3 test_sec7_7_4 test_sec7_7_5 test_sec7_8_1 test_sec7_8_2 test_sec7_8_3 test_sec7_9_1 test_sec7_9_2 test_sec7_9_3 test_sec7_9_4 test_sec7_10 test_sec7_11 test_sec7_12_1 test_sec7_12_2 test_sec7_13_1 test_sec7_13_2 test_sec7_15 test_sec7_16_1 test_sec7_16_2 test_sec7_18_1 test_sec7_18_2 test_sec7_18_3_1 test_sec7_18_3_2 test_sec7_19_1 test_sec7_19_5 test_sec9_2 test_sec9_4_4)
 
 include_directories(SYSTEM ${CMOCKA_INCLUDE_DIR})
 
diff --git a/tests/conformance/sec9_4_4/data1.xml b/tests/conformance/sec9_4_4/data1.xml
new file mode 100644
index 0000000..3ae8fe6
--- /dev/null
+++ b/tests/conformance/sec9_4_4/data1.xml
@@ -0,0 +1,2 @@
+<leaf1 xmlns="urn:cesnet:mod10"></leaf1>
+<leaf3 xmlns="urn:cesnet:mod10"></leaf3>
diff --git a/tests/conformance/sec9_4_4/data2.xml b/tests/conformance/sec9_4_4/data2.xml
new file mode 100644
index 0000000..efb0f84
--- /dev/null
+++ b/tests/conformance/sec9_4_4/data2.xml
@@ -0,0 +1 @@
+<llist xmlns="urn:cesnet:mod10"></llist>
diff --git a/tests/conformance/sec9_4_4/data3.xml b/tests/conformance/sec9_4_4/data3.xml
new file mode 100644
index 0000000..aeaf7d8
--- /dev/null
+++ b/tests/conformance/sec9_4_4/data3.xml
@@ -0,0 +1 @@
+<llist xmlns="urn:cesnet:mod10">test1234</llist>
diff --git a/tests/conformance/sec9_4_4/data4.xml b/tests/conformance/sec9_4_4/data4.xml
new file mode 100644
index 0000000..6ca4699
--- /dev/null
+++ b/tests/conformance/sec9_4_4/data4.xml
@@ -0,0 +1 @@
+<llist xmlns="urn:cesnet:mod10">This is a example sentence. This string is very long.</llist>
diff --git a/tests/conformance/sec9_4_4/data5.xml b/tests/conformance/sec9_4_4/data5.xml
new file mode 100644
index 0000000..42cdc5e
--- /dev/null
+++ b/tests/conformance/sec9_4_4/data5.xml
@@ -0,0 +1,8 @@
+<leaf1 xmlns="urn:cesnet:mod10"></leaf1>
+<leaf3 xmlns="urn:cesnet:mod10">my_string</leaf3>
+<llist xmlns="urn:cesnet:mod10">test123</llist>
+<llist xmlns="urn:cesnet:mod10">t</llist>
+<llist xmlns="urn:cesnet:mod10">test</llist>
+<llist xmlns="urn:cesnet:mod10">test llist</llist>
+<llist xmlns="urn:cesnet:mod10">test references</llist>
+<llist xmlns="urn:cesnet:mod10">This is a example sentence. This string is not long.</llist>
diff --git a/tests/conformance/sec9_4_4/mod1.yang b/tests/conformance/sec9_4_4/mod1.yang
new file mode 100644
index 0000000..3369f3d
--- /dev/null
+++ b/tests/conformance/sec9_4_4/mod1.yang
@@ -0,0 +1,14 @@
+module mod1 {
+    prefix abc;
+    namespace "urn:cesnet:mod1";
+
+    typedef my {
+        type string {
+            length "1 .. 255" {
+                description "test description";
+
+                description "test"; // duplicated
+            }
+        }
+    }
+}
diff --git a/tests/conformance/sec9_4_4/mod10.yang b/tests/conformance/sec9_4_4/mod10.yang
new file mode 100644
index 0000000..659360a
--- /dev/null
+++ b/tests/conformance/sec9_4_4/mod10.yang
@@ -0,0 +1,35 @@
+module mod10 {
+    prefix abc;
+    namespace "urn:cesnet:mod10";
+
+    typedef my2 {
+        type my {
+            length "1..52" {
+                reference "test reference";
+                error-app-tag "test tag";
+                description "test description";
+                error-message "test error message";
+            }
+        }
+    }
+
+    typedef my {
+        type string;
+    }
+
+    leaf leaf1 {
+        type my;
+    }
+
+    leaf-list llist {
+        type my2 {
+            length "min..7 | 10 | 15 .. 25 | 26 .. max";
+        }
+    }
+
+    leaf leaf3 {
+        type my {
+            length "min .. max";
+        }
+    }
+}
diff --git a/tests/conformance/sec9_4_4/mod2.yang b/tests/conformance/sec9_4_4/mod2.yang
new file mode 100644
index 0000000..27ed9fd
--- /dev/null
+++ b/tests/conformance/sec9_4_4/mod2.yang
@@ -0,0 +1,15 @@
+module mod2 {
+    prefix abc;
+    namespace "urn:cesnet:mod2";
+
+    typedef my {
+        type string {
+            length 1..255 {
+                reference "test reference";
+                description "test description";
+
+                reference "test"; // duplicated
+            }
+        }
+    }
+}
diff --git a/tests/conformance/sec9_4_4/mod3.yang b/tests/conformance/sec9_4_4/mod3.yang
new file mode 100644
index 0000000..52d304b
--- /dev/null
+++ b/tests/conformance/sec9_4_4/mod3.yang
@@ -0,0 +1,16 @@
+module mod2 {
+    prefix abc;
+    namespace "urn:cesnet:mod2";
+
+    typedef my {
+        type string {
+            length "1..255" {
+                reference "test reference";
+                error-app-tag "test tag";
+                description "test description";
+
+                error-app-tag "test"; // duplicated
+            }
+        }
+    }
+}
diff --git a/tests/conformance/sec9_4_4/mod4.yang b/tests/conformance/sec9_4_4/mod4.yang
new file mode 100644
index 0000000..24aa2cd
--- /dev/null
+++ b/tests/conformance/sec9_4_4/mod4.yang
@@ -0,0 +1,17 @@
+module mod4 {
+    prefix abc;
+    namespace "urn:cesnet:mod4";
+
+    typedef my {
+        type string {
+            length "1..255" {
+                reference "test reference";
+                error-app-tag "test tag";
+                description "test description";
+                error-message "test error message";
+
+                error-message "test"; // duplicated
+            }
+        }
+    }
+}
diff --git a/tests/conformance/sec9_4_4/mod5.yang b/tests/conformance/sec9_4_4/mod5.yang
new file mode 100644
index 0000000..25f9f9c
--- /dev/null
+++ b/tests/conformance/sec9_4_4/mod5.yang
@@ -0,0 +1,24 @@
+module mod5 {
+    prefix abc;
+    namespace "urn:cesnet:mod5";
+
+    typedef my-base-str-type {
+         type string {
+             length "1..255";
+         }
+     }
+
+    leaf leaf1 {
+        type my-base-str-type {
+            // legal length refinement
+            length "11 | 42..max"; // 11 | 42..255
+        }
+    }
+
+    leaf leaf2 {
+        type my-base-str-type {
+            // illegal length refinement
+            length "1..999";
+        }
+    }
+}
diff --git a/tests/conformance/sec9_4_4/mod6.yang b/tests/conformance/sec9_4_4/mod6.yang
new file mode 100644
index 0000000..07aa430
--- /dev/null
+++ b/tests/conformance/sec9_4_4/mod6.yang
@@ -0,0 +1,10 @@
+module mod6 {
+    prefix abc;
+    namespace "urn:cesnet:mod6";
+
+    leaf lef1 {
+        type string {
+            length "-1 .. 100";
+        }
+    }
+}
diff --git a/tests/conformance/sec9_4_4/mod7.yang b/tests/conformance/sec9_4_4/mod7.yang
new file mode 100644
index 0000000..0f1e3cb
--- /dev/null
+++ b/tests/conformance/sec9_4_4/mod7.yang
@@ -0,0 +1,17 @@
+module mod7 {
+    prefix abc;
+    namespace "urn:cesnet:mod7";
+
+    typedef my-base-str-type {
+         type string {
+             length "1..255";
+         }
+     }
+
+    leaf leaf1 {
+        type my-base-str-type {
+            // legal length refinement
+            length "42..max | 11"; // wrong order
+        }
+    }
+}
diff --git a/tests/conformance/sec9_4_4/mod8.yang b/tests/conformance/sec9_4_4/mod8.yang
new file mode 100644
index 0000000..aa3ab0e
--- /dev/null
+++ b/tests/conformance/sec9_4_4/mod8.yang
@@ -0,0 +1,16 @@
+module mod8 {
+    prefix abc;
+    namespace "urn:cesnet:mod8";
+
+    typedef my {
+        type string {
+            length "1..255";
+        }
+    }
+
+    leaf leaf {
+        type my {
+            length "min .. 10 | 10 .. 25 | 27 .. max";
+        }
+    }
+}
diff --git a/tests/conformance/sec9_4_4/mod9.yang b/tests/conformance/sec9_4_4/mod9.yang
new file mode 100644
index 0000000..0e53d7b
--- /dev/null
+++ b/tests/conformance/sec9_4_4/mod9.yang
@@ -0,0 +1,16 @@
+module mod9 {
+    prefix abc;
+    namespace "urn:cesnet:mod9";
+
+    typedef my {
+        type string {
+            length "1..255";
+        }
+    }
+
+    leaf leaf {
+        type string {
+            length "min .. 25 | 10 .. 26 | 27 .. max";
+        }
+    }
+}
diff --git a/tests/conformance/test_sec9_4_4.c b/tests/conformance/test_sec9_4_4.c
new file mode 100644
index 0000000..87c09a1
--- /dev/null
+++ b/tests/conformance/test_sec9_4_4.c
@@ -0,0 +1,143 @@
+/**
+ * @file test_sec9_4_4.c
+ * @author Pavol Vican
+ * @brief Cmocka test for RFC 6020 section 9.4.4 (also 9.4.4.1) conformance.
+ *
+ * Copyright (c) 2016 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 <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <errno.h>
+#include <unistd.h>
+#include <cmocka.h>
+#include <string.h>
+
+#include "../config.h"
+#include "../../src/libyang.h"
+
+#define TEST_DIR "sec9_4_4"
+#define TEST_NAME test_sec7_9_4_4
+#define TEST_SCHEMA_COUNT 10
+#define TEST_SCHEMA_LOAD_FAIL 1,1,1,1,1,1,1,1,1,0
+#define TEST_DATA_FILE_COUNT 5
+#define TEST_DATA_FILE_LOAD_FAIL 0,1,1,1,0
+
+struct state {
+    struct ly_ctx *ctx;
+    struct lyd_node *node;
+};
+
+static int
+setup_f(void **state)
+{
+    struct state *st;
+
+    (*state) = st = calloc(1, sizeof *st);
+    if (!st) {
+        fprintf(stderr, "Memory allocation error");
+        return -1;
+    }
+
+    /* libyang context */
+    st->ctx = ly_ctx_new(TESTS_DIR "/conformance/" TEST_DIR);
+    if (!st->ctx) {
+        fprintf(stderr, "Failed to create context.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int
+teardown_f(void **state)
+{
+    struct state *st = (*state);
+
+    lyd_free_withsiblings(st->node);
+    ly_ctx_destroy(st->ctx, NULL);
+    free(st);
+    (*state) = NULL;
+
+    return 0;
+}
+
+static void
+TEST_STRING_LENGTH(void **state)
+{
+    struct state *st = (*state);
+    const int schemas_fail[] = {TEST_SCHEMA_LOAD_FAIL};
+    const int data_files_fail[] = {TEST_DATA_FILE_LOAD_FAIL};
+    char buf[1024];
+    LYS_INFORMAT schema_format = LYS_IN_YANG;
+    const struct lys_module *mod;
+    int i, j, ret;
+
+    for (i = 0; i < 2; ++i) {
+        for (j = 0; j < TEST_SCHEMA_COUNT; ++j) {
+            sprintf(buf, TESTS_DIR "/conformance/" TEST_DIR "/mod%d.%s", j + 1, (schema_format == LYS_IN_YANG ? "yang" : "yin"));
+            mod = lys_parse_path(st->ctx, buf, schema_format);
+            if (schemas_fail[j]) {
+                assert_ptr_equal(mod, NULL);
+            } else {
+                assert_ptr_not_equal(mod, NULL);
+            }
+        }
+
+        for (j = 0; j < TEST_DATA_FILE_COUNT; ++j) {
+            sprintf(buf, TESTS_DIR "/conformance/" TEST_DIR "/data%d.xml", j + 1);
+            st->node = lyd_parse_path(st->ctx, buf, LYD_XML, LYD_OPT_CONFIG);
+            if (data_files_fail[j]) {
+                assert_ptr_equal(st->node, NULL);
+            } else {
+                assert_ptr_not_equal(st->node, NULL);
+            }
+            lyd_free_withsiblings(st->node);
+            st->node = NULL;
+        }
+
+        if (schema_format == LYS_IN_YANG) {
+            /* convert the modules */
+            for (j = 0; j < TEST_SCHEMA_COUNT; ++j) {
+                sprintf(buf, BUILD_DIR "/yang2yin "
+                             TESTS_DIR "/conformance/" TEST_DIR "/mod%d.yang "
+                             TESTS_DIR "/conformance/" TEST_DIR "/mod%d.yin", j + 1, j + 1);
+                ret = system(buf);
+                if (ret == -1) {
+                    fprintf(stderr, "system() failed (%s).\n", strerror(errno));
+                    fail();
+                } else if (WEXITSTATUS(ret) != 0) {
+                    fprintf(stderr, "Executing command \"%s\" finished with %d.\n", buf, WEXITSTATUS(ret));
+                    fail();
+                }
+            }
+
+            schema_format = LYS_IN_YIN;
+        } else {
+            /* remove the modules */
+            for (j = 0; j < TEST_SCHEMA_COUNT; ++j) {
+                sprintf(buf, TESTS_DIR "/conformance/" TEST_DIR "/mod%d.yin", j + 1);
+                if (unlink(buf)) {
+                    fprintf(stderr, "unlink() on \"%s\" failed (%s).\n", buf, strerror(errno));
+                }
+            }
+        }
+    }
+}
+
+int
+main(void)
+{
+    const struct CMUnitTest tests[] = {
+        cmocka_unit_test_setup_teardown(TEST_STRING_LENGTH, setup_f, teardown_f),
+    };
+
+    return cmocka_run_group_tests(tests, NULL, NULL);
+}