blob: c82dbb49b3f14e538d0877f28f207ee97d363347 [file] [log] [blame]
Radek Krejci85ac8312021-03-03 20:21:33 +01001/*
2 * @file test_schema_extensions.c
3 * @author: Radek Krejci <rkrejci@cesnet.cz>
4 * @brief unit tests for YANG (YIN) extension statements and their instances in schemas
5 *
6 * Copyright (c) 2018-2021 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#include "test_schema.h"
15
16#include <string.h>
17
18#include "context.h"
19#include "log.h"
Michal Vasko633ae8a2022-08-25 09:52:02 +020020#include "plugins_exts.h"
Radek Krejci85ac8312021-03-03 20:21:33 +010021#include "tree_schema.h"
22
23void
24test_extension_argument(void **state)
25{
Michal Vasko4de7d072021-07-09 09:13:18 +020026 struct lys_module *mod;
Radek Krejci85ac8312021-03-03 20:21:33 +010027 const char *mod_def_yang = "module a {\n"
28 " namespace \"urn:a\";\n"
29 " prefix a;\n\n"
30 " extension e {\n"
31 " argument name;\n"
32 " }\n\n"
33 " a:e \"aaa\";\n"
34 "}\n";
35 const char *mod_def_yin =
36 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
37 "<module name=\"a\"\n"
38 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
39 " xmlns:a=\"urn:a\">\n"
40 " <namespace uri=\"urn:a\"/>\n"
41 " <prefix value=\"a\"/>\n\n"
42 " <extension name=\"e\">\n"
43 " <argument name=\"name\"/>\n"
44 " </extension>\n\n"
45 " <a:e name=\"aaa\"/>\n"
46 "</module>\n";
47 const char *mod_test_yin, *mod_test_yang;
48 char *printed;
49
50 mod_test_yang = "module b {\n"
51 " namespace \"urn:b\";\n"
52 " prefix b;\n\n"
53 " import a {\n"
54 " prefix a;\n"
55 " }\n\n"
56 " a:e \"xxx\";\n"
57 "}\n";
58 mod_test_yin =
59 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
60 "<module name=\"b\"\n"
61 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
62 " xmlns:b=\"urn:b\"\n"
63 " xmlns:a=\"urn:a\">\n"
64 " <namespace uri=\"urn:b\"/>\n"
65 " <prefix value=\"b\"/>\n"
66 " <import module=\"a\">\n"
67 " <prefix value=\"a\"/>\n"
68 " </import>\n\n"
69 " <a:e name=\"xxx\"/>\n"
70 "</module>\n";
71
72 /* from YANG */
73 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_def_yang);
74 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, mod_test_yang, LYS_IN_YANG, &mod));
75 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
76 assert_string_equal(printed, mod_test_yang);
77 free(printed);
78
79 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
80 assert_string_equal(printed, mod_test_yin);
81 free(printed);
82
83 assert_non_null(mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL));
84 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
85 assert_string_equal(printed, mod_def_yang);
86 free(printed);
87
88 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
89 assert_string_equal(printed, mod_def_yin);
90 free(printed);
91
92 /* context reset */
Radek Krejci90ed21e2021-04-12 14:47:46 +020093 ly_ctx_destroy(UTEST_LYCTX);
Radek Krejci85ac8312021-03-03 20:21:33 +010094 ly_ctx_new(NULL, 0, &UTEST_LYCTX);
95
96 /* from YIN */
97 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_def_yin);
98 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, &mod));
99 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
100 assert_string_equal(printed, mod_test_yang);
101 free(printed);
102
103 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
104 assert_string_equal(printed, mod_test_yin);
105 free(printed);
106
107 assert_non_null(mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL));
108 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
109 assert_string_equal(printed, mod_def_yang);
110 free(printed);
111
112 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
113 assert_string_equal(printed, mod_def_yin);
114 free(printed);
115}
116
117void
118test_extension_argument_element(void **state)
119{
Michal Vasko4de7d072021-07-09 09:13:18 +0200120 struct lys_module *mod;
Radek Krejci85ac8312021-03-03 20:21:33 +0100121 const char *mod_def_yang = "module a {\n"
122 " namespace \"urn:a\";\n"
123 " prefix a;\n\n"
124 " extension e {\n"
125 " argument name {\n"
126 " yin-element true;\n"
127 " }\n"
128 " }\n\n"
129 " a:e \"aaa\";\n"
130 "}\n";
131 const char *mod_def_yin =
132 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
133 "<module name=\"a\"\n"
134 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
135 " xmlns:a=\"urn:a\">\n"
136 " <namespace uri=\"urn:a\"/>\n"
137 " <prefix value=\"a\"/>\n\n"
138 " <extension name=\"e\">\n"
139 " <argument name=\"name\">\n"
140 " <yin-element value=\"true\"/>\n"
141 " </argument>\n"
142 " </extension>\n\n"
143 " <a:e>\n"
144 " <a:name>aaa</a:name>\n"
145 " </a:e>\n"
146 "</module>\n";
147 const char *mod_test_yin, *mod_test_yang;
148 char *printed;
149
150 mod_test_yang = "module b {\n"
151 " namespace \"urn:b\";\n"
152 " prefix b;\n\n"
153 " import a {\n"
154 " prefix a;\n"
155 " }\n\n"
156 " a:e \"xxx\";\n"
157 "}\n";
158 mod_test_yin =
159 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
160 "<module name=\"b\"\n"
161 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
162 " xmlns:b=\"urn:b\"\n"
163 " xmlns:a=\"urn:a\">\n"
164 " <namespace uri=\"urn:b\"/>\n"
165 " <prefix value=\"b\"/>\n"
166 " <import module=\"a\">\n"
167 " <prefix value=\"a\"/>\n"
168 " </import>\n\n"
169 " <a:e>\n"
170 " <a:name>xxx</a:name>\n"
171 " </a:e>\n"
172 "</module>\n";
173
174 /* from YANG */
175 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_def_yang);
176 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, mod_test_yang, LYS_IN_YANG, &mod));
177 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
178 assert_string_equal(printed, mod_test_yang);
179 free(printed);
180
181 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
182 assert_string_equal(printed, mod_test_yin);
183 free(printed);
184
185 assert_non_null(mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL));
186 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
187 assert_string_equal(printed, mod_def_yang);
188 free(printed);
189
190 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
191 assert_string_equal(printed, mod_def_yin);
192 free(printed);
193
194 /* context reset */
Radek Krejci90ed21e2021-04-12 14:47:46 +0200195 ly_ctx_destroy(UTEST_LYCTX);
Radek Krejci85ac8312021-03-03 20:21:33 +0100196 ly_ctx_new(NULL, 0, &UTEST_LYCTX);
197
198 /* from YIN */
199 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_def_yin);
200 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, &mod));
201 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
202 assert_string_equal(printed, mod_test_yang);
203 free(printed);
204
205 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
206 assert_string_equal(printed, mod_test_yin);
207 free(printed);
208
209 assert_non_null(mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL));
210 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
211 assert_string_equal(printed, mod_def_yang);
212 free(printed);
213
214 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
215 assert_string_equal(printed, mod_def_yin);
216 free(printed);
217
218 /* invalid */
219 mod_test_yang = "module x { namespace \"urn:x\"; prefix x; import a { prefix a; } a:e; }";
220 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yang, LYS_IN_YANG, NULL));
221 CHECK_LOG_CTX("Extension instance \"a:e\" misses argument element \"name\".", "/x:{extension='a:e'}");
222
223 mod_test_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
224 "<module name=\"x\"\n"
225 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
226 " xmlns:x=\"urn:x\"\n"
227 " xmlns:a=\"urn:a\">\n"
228 " <namespace uri=\"urn:x\"/>\n"
229 " <prefix value=\"x\"/>\n"
230 " <import module=\"a\">\n"
231 " <prefix value=\"a\"/>\n"
232 " </import>\n\n"
233 " <a:e/>\n"
234 "</module>\n";
235 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, NULL));
236 CHECK_LOG_CTX("Extension instance \"a:e\" misses argument element \"name\".", "/x:{extension='a:e'}");
237
238 mod_test_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
239 "<module name=\"x\"\n"
240 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
241 " xmlns:x=\"urn:x\"\n"
242 " xmlns:a=\"urn:a\">\n"
243 " <namespace uri=\"urn:x\"/>\n"
244 " <prefix value=\"x\"/>\n"
245 " <import module=\"a\">\n"
246 " <prefix value=\"a\"/>\n"
247 " </import>\n\n"
248 " <a:e name=\"xxx\"/>\n"
249 "</module>\n";
250 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, NULL));
251 CHECK_LOG_CTX("Extension instance \"a:e\" misses argument element \"name\".", "/x:{extension='a:e'}");
252
253 mod_test_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
254 "<module name=\"x\"\n"
255 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
256 " xmlns:x=\"urn:x\"\n"
257 " xmlns:a=\"urn:a\">\n"
258 " <namespace uri=\"urn:x\"/>\n"
259 " <prefix value=\"x\"/>\n"
260 " <import module=\"a\">\n"
261 " <prefix value=\"a\"/>\n"
262 " </import>\n\n"
263 " <a:e>\n"
264 " <x:name>xxx</x:name>\n"
265 " </a:e>\n"
266 "</module>\n";
267 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, NULL));
268 CHECK_LOG_CTX("Extension instance \"a:e\" element and its argument element \"name\" are expected in the same namespace, but they differ.",
269 "/x:{extension='a:e'}");
270
271 mod_test_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
272 "<module name=\"x\"\n"
273 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
274 " xmlns:x=\"urn:x\"\n"
275 " xmlns:a=\"urn:a\">\n"
276 " <namespace uri=\"urn:x\"/>\n"
277 " <prefix value=\"x\"/>\n"
278 " <import module=\"a\">\n"
279 " <prefix value=\"a\"/>\n"
280 " </import>\n\n"
281 " <a:e>\n"
282 " <a:value>xxx</a:value>\n"
283 " </a:e>\n"
284 "</module>\n";
285 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, NULL));
286 CHECK_LOG_CTX("Extension instance \"a:e\" expects argument element \"name\" as its first XML child, but \"value\" element found.",
287 "/x:{extension='a:e'}");
288
289}
Michal Vasko633ae8a2022-08-25 09:52:02 +0200290
291void
292test_extension_compile(void **state)
293{
294 struct lys_module *mod;
295 struct lysc_ctx cctx = {0};
296 struct lysp_ext_instance ext_p = {0};
297 struct lysp_stmt child = {0};
298 struct lysc_ext_instance ext_c = {0};
299 struct lysc_ext_substmt *substmt;
300 LY_ERR rc = LY_SUCCESS;
301
302 /* current module, whatever */
303 mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "yang");
304 assert_true(mod);
305
306 /* compile context */
307 cctx.ctx = UTEST_LYCTX;
308 cctx.cur_mod = mod;
309 cctx.pmod = mod->parsed;
310 cctx.path_len = 1;
311 cctx.path[0] = '/';
312
313 /* parsed ext instance */
314 lydict_insert(UTEST_LYCTX, "pref:my-ext", 0, &ext_p.name);
315 ext_p.format = LY_VALUE_JSON;
316 ext_p.parent_stmt = LY_STMT_MODULE;
317
318 /* compiled ext instance */
319 ext_c.parent_stmt = ext_p.parent_stmt;
320 // ext_c.parent =
321 LY_ARRAY_NEW_GOTO(UTEST_LYCTX, ext_c.substmts, substmt, rc, cleanup);
322
323 /*
324 * error-message
325 */
326 ext_p.child = &child;
327 lydict_insert(UTEST_LYCTX, "error-message", 0, &child.stmt);
328 lydict_insert(UTEST_LYCTX, "my error", 0, &child.arg);
329 child.format = LY_VALUE_JSON;
330 child.kw = LY_STMT_ERROR_MESSAGE;
331
332 substmt->stmt = LY_STMT_ERROR_MESSAGE;
333 substmt->cardinality = LY_STMT_CARD_OPT;
334 substmt->storage = &ext_c.data;
335
336 /* compile */
337 assert_int_equal(LY_SUCCESS, lys_compile_extension_instance(&cctx, &ext_p, &ext_c));
338
339 /* check */
340 assert_string_equal(ext_c.data, "my error");
341
342cleanup:
343 lydict_remove(UTEST_LYCTX, ext_p.name);
344 lydict_remove(UTEST_LYCTX, child.stmt);
345 lydict_remove(UTEST_LYCTX, child.arg);
346 LY_ARRAY_FREE(ext_c.substmts);
347
348 lydict_remove(UTEST_LYCTX, ext_c.data);
349 if (rc) {
350 fail();
351 }
352}