1 /**
2 * @file test_sec9_10.c
3 * @author Pavol Vican
4 * @brief Cmocka test for RFC 6020 section 9.10 conformance.
5 *
6 * Copyright (c) 2016 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <setjmp.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include <stdarg.h>
21 #include <cmocka.h>
22 #include <string.h>
23 #include <sys/wait.h>
24
25 #include "tests/config.h"
26 #include "libyang.h"
27
28 #define TEST_DIR "sec9_10"
29 #define TEST_NAME test_sec9_10
30 #define TEST_SCHEMA_COUNT 3
31 #define TEST_SCHEMA_LOAD_FAIL 1,1,0
32 #define TEST_DATA_FILE_COUNT 6
33 #define TEST_DATA_FILE_LOAD_FAIL 1,1,0,1,0,1
34
35 struct state {
36 struct ly_ctx *ctx;
37 struct lyd_node *node;
38 };
39
40 static int
setup_f(void ** state)41 setup_f(void **state)
42 {
43 struct state *st;
44
45 (*state) = st = calloc(1, sizeof *st);
46 if (!st) {
47 fprintf(stderr, "Memory allocation error");
48 return -1;
49 }
50
51 /* libyang context */
52 st->ctx = ly_ctx_new(TESTS_DIR "/conformance/" TEST_DIR, 0);
53 if (!st->ctx) {
54 fprintf(stderr, "Failed to create context.\n");
55 return -1;
56 }
57
58 return 0;
59 }
60
61 static int
teardown_f(void ** state)62 teardown_f(void **state)
63 {
64 struct state *st = (*state);
65
66 lyd_free_withsiblings(st->node);
67 ly_ctx_destroy(st->ctx, NULL);
68 free(st);
69 (*state) = NULL;
70
71 return 0;
72 }
73
74 static void
TEST_IDENTITYREF(void ** state)75 TEST_IDENTITYREF(void **state)
76 {
77 struct state *st = (*state);
78 const int schemas_fail[] = {TEST_SCHEMA_LOAD_FAIL};
79 const int data_files_fail[] = {TEST_DATA_FILE_LOAD_FAIL};
80 char buf[1024];
81 LYS_INFORMAT schema_format = LYS_IN_YANG;
82 const struct lys_module *mod;
83 int i, j, ret;
84
85 for (i = 0; i < 2; ++i) {
86 for (j = 0; j < TEST_SCHEMA_COUNT; ++j) {
87 sprintf(buf, TESTS_DIR "/conformance/" TEST_DIR "/mod%d.%s", j + 1, (schema_format == LYS_IN_YANG ? "yang" : "yin"));
88 mod = lys_parse_path(st->ctx, buf, schema_format);
89 if (schemas_fail[j]) {
90 assert_ptr_equal(mod, NULL);
91 } else {
92 assert_ptr_not_equal(mod, NULL);
93 }
94 }
95
96 for (j = 0; j < TEST_DATA_FILE_COUNT; ++j) {
97 sprintf(buf, TESTS_DIR "/conformance/" TEST_DIR "/data%d.xml", j + 1);
98 st->node = lyd_parse_path(st->ctx, buf, LYD_XML, LYD_OPT_CONFIG);
99 if (data_files_fail[j]) {
100 assert_ptr_equal(st->node, NULL);
101 } else {
102 assert_ptr_not_equal(st->node, NULL);
103 }
104 lyd_free_withsiblings(st->node);
105 st->node = NULL;
106 }
107
108 if (schema_format == LYS_IN_YANG) {
109 /* convert the modules */
110 for (j = 0; j < TEST_SCHEMA_COUNT; ++j) {
111 sprintf(buf, BUILD_DIR "/yang2yin "
112 TESTS_DIR "/conformance/" TEST_DIR "/mod%d.yang "
113 TESTS_DIR "/conformance/" TEST_DIR "/mod%d.yin", j + 1, j + 1);
114 ret = system(buf);
115 if (ret == -1) {
116 fprintf(stderr, "system() failed (%s).\n", strerror(errno));
117 fail();
118 } else if (WEXITSTATUS(ret) != 0) {
119 fprintf(stderr, "Executing command \"%s\" finished with %d.\n", buf, WEXITSTATUS(ret));
120 fail();
121 }
122 }
123
124 schema_format = LYS_IN_YIN;
125 ly_ctx_destroy(st->ctx, NULL);
126 st->ctx = ly_ctx_new(TESTS_DIR "/conformance/" TEST_DIR, 0);
127 if (!st->ctx) {
128 fprintf(stderr, "Failed to create context.\n");
129 fail();
130 }
131 } else {
132 /* remove the modules */
133 for (j = 0; j < TEST_SCHEMA_COUNT; ++j) {
134 sprintf(buf, TESTS_DIR "/conformance/" TEST_DIR "/mod%d.yin", j + 1);
135 if (unlink(buf)) {
136 fprintf(stderr, "unlink() on \"%s\" failed (%s).\n", buf, strerror(errno));
137 }
138 }
139 }
140 }
141 }
142
143 /* in data6.xml we have value defined in mod.yang which is just imported in previous test and
144 * the data are not valid. Here, mod.yang is loaded as import by mod-dflt.yang and then explicitly
145 * changed to implemented.
146 */
147 static void
TEST_IDENTITYREF2(void ** state)148 TEST_IDENTITYREF2(void **state)
149 {
150 struct state *st = (*state);
151 const struct lys_module *mod;
152 const char *middle_data = "<test xmlns=\"urn:cesnet:mod3\" xmlns:mm=\"urn:cesnet:mod-middle\">mm:j4</test>";
153
154 /* mod is imported */
155 mod = lys_parse_path(st->ctx, TESTS_DIR "/conformance/" TEST_DIR "/mod3.yang", LYS_IN_YANG);
156 assert_ptr_not_equal(mod, NULL);
157
158 /* invalid identityref value from not-implemented schema */
159 st->node = lyd_parse_path(st->ctx, TESTS_DIR "/conformance/" TEST_DIR "/data6.xml", LYD_XML, LYD_OPT_CONFIG);
160 assert_ptr_equal(st->node, NULL);
161
162 mod = lys_parse_path(st->ctx, TESTS_DIR "/conformance/" TEST_DIR "/mod-dflt-invalid.yang", LYS_IN_YANG);
163 assert_ptr_equal(mod, NULL);
164
165 mod = lys_parse_path(st->ctx, TESTS_DIR "/conformance/" TEST_DIR "/mod-dflt.yang", LYS_IN_YANG);
166 assert_ptr_not_equal(mod, NULL);
167
168 /* set mod to be implemented */
169 mod = ly_ctx_get_module(st->ctx, "mod", NULL, 0);
170 assert_int_equal(lys_set_implemented(mod), 0);
171
172 /* mod is implemented so the identityref value is valid here */
173 st->node = lyd_parse_path(st->ctx, TESTS_DIR "/conformance/" TEST_DIR "/data6.xml", LYD_XML, LYD_OPT_CONFIG);
174 assert_ptr_not_equal(st->node, NULL);
175 lyd_free_withsiblings(st->node);
176
177 /* but mod-middle is still not implemented, so mod-middle:j1 value is invalid */
178 st->node = lyd_parse_mem(st->ctx, middle_data, LYD_XML, LYD_OPT_CONFIG);
179 assert_ptr_equal(st->node, NULL);
180
181 /* but making it implemented the data can be loaded */
182 assert_int_equal(lys_set_implemented(ly_ctx_get_module(st->ctx, "mod-middle", NULL, 0)), 0);
183 st->node = lyd_parse_mem(st->ctx, middle_data, LYD_XML, LYD_OPT_CONFIG);
184 assert_ptr_not_equal(st->node, NULL);
185 }
186
187 int
main(void)188 main(void)
189 {
190 const struct CMUnitTest tests[] = {
191 cmocka_unit_test_setup_teardown(TEST_IDENTITYREF, setup_f, teardown_f),
192 cmocka_unit_test_setup_teardown(TEST_IDENTITYREF2, setup_f, teardown_f),
193 };
194
195 return cmocka_run_group_tests(tests, NULL, NULL);
196 }
197