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);
+}