blob: adbe0850443e21a572a15735ff8933fb5ba4bc38 [file] [log] [blame]
Michal Vaskoc636ea42022-09-16 10:20:31 +02001/**
Radek Krejci3a4889a2020-05-19 17:01:58 +02002 * @file test_schema.c
Michal Vaskoc636ea42022-09-16 10:20:31 +02003 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @author Michal Vasko <mvasko@cesnet.cz>
Radek Krejci3a4889a2020-05-19 17:01:58 +02005 * @brief unit tests for schema related functions
6 *
Michal Vaskoc636ea42022-09-16 10:20:31 +02007 * Copyright (c) 2018 - 2022 CESNET, z.s.p.o.
Radek Krejci3a4889a2020-05-19 17:01:58 +02008 *
9 * This source code is licensed under BSD 3-Clause License (the "License").
10 * You may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * https://opensource.org/licenses/BSD-3-Clause
14 */
Radek Iša56ca9e42020-09-08 18:42:00 +020015#define _UTEST_MAIN_
Michal Vaskoc636ea42022-09-16 10:20:31 +020016#include "utests.h"
Radek Krejci18abde42020-06-13 20:04:39 +020017
Radek Krejcica376bd2020-06-11 16:04:06 +020018#include <string.h>
19
Michal Vaskoc636ea42022-09-16 10:20:31 +020020#include "compat.h"
21#include "context.h"
Radek Krejci18abde42020-06-13 20:04:39 +020022#include "log.h"
23#include "parser_schema.h"
Michal Vaskoc636ea42022-09-16 10:20:31 +020024#include "plugins_exts.h"
Radek Krejci8297b792020-08-16 14:49:05 +020025#include "set.h"
Michal Vaskoc636ea42022-09-16 10:20:31 +020026#include "tree_edit.h"
Radek Krejci18abde42020-06-13 20:04:39 +020027#include "tree_schema.h"
Michal Vaskoc636ea42022-09-16 10:20:31 +020028#include "tree_schema_internal.h"
Radek Krejci3a4889a2020-05-19 17:01:58 +020029
Michal Vaskoc636ea42022-09-16 10:20:31 +020030static LY_ERR
Radek Krejci18abde42020-06-13 20:04:39 +020031test_imp_clb(const char *UNUSED(mod_name), const char *UNUSED(mod_rev), const char *UNUSED(submod_name),
Radek Krejcib4ac5a92020-11-23 17:54:33 +010032 const char *UNUSED(sub_rev), void *user_data, LYS_INFORMAT *format,
33 const char **module_data, void (**free_module_data)(void *model_data, void *user_data))
Radek Krejci18abde42020-06-13 20:04:39 +020034{
35 *module_data = user_data;
Radek Krejci85ac8312021-03-03 20:21:33 +010036 if ((*module_data)[0] == '<') {
37 *format = LYS_IN_YIN;
38 } else {
39 *format = LYS_IN_YANG;
40 }
Radek Krejci18abde42020-06-13 20:04:39 +020041 *free_module_data = NULL;
42 return LY_SUCCESS;
43}
Radek Krejci3a4889a2020-05-19 17:01:58 +020044
Michal Vaskoc636ea42022-09-16 10:20:31 +020045#define TEST_YANG_MODULE_10(MOD_NAME, MOD_PREFIX, MOD_NS, CONTENT) \
46 "module "MOD_NAME" { namespace "MOD_NS"; prefix "MOD_PREFIX"; "CONTENT"}"
Radek Krejci18abde42020-06-13 20:04:39 +020047
Michal Vaskoc636ea42022-09-16 10:20:31 +020048#define TEST_YANG_MODULE_11(MOD_NAME, MOD_PREFIX, MOD_NS, CONTENT) \
49 "module "MOD_NAME" {yang-version 1.1; namespace "MOD_NS"; prefix "MOD_PREFIX"; "CONTENT"}"
Radek Krejci3a4889a2020-05-19 17:01:58 +020050
Michal Vaskoc636ea42022-09-16 10:20:31 +020051#define TEST_YIN_MODULE_10(MOD_NAME, MOD_PREFIX, MOD_NS, CONTENT) \
52 "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" name=\""MOD_NAME"\">" \
53 "<namespace uri=\""MOD_NS"\"/><prefix value=\""MOD_PREFIX"\"/>"CONTENT"</module>"
54
55#define TEST_YIN_MODULE_11(MOD_NAME, MOD_PREFIX, MOD_NS, CONTENT) \
56 "<module xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\" name=\""MOD_NAME"\"><yang-version value=\"1.1\"/>" \
57 "<namespace uri=\""MOD_NS"\"/><prefix value=\""MOD_PREFIX"\"/>"CONTENT"</module>"
58
59#define TEST_SCHEMA_STR(RFC7950, YIN, MOD_NAME, CONTENT, STR) \
60 if (YIN) { \
61 if (RFC7950) { \
62 STR = TEST_YIN_MODULE_11(MOD_NAME, MOD_NAME, "urn:libyang:test:"MOD_NAME, CONTENT); \
63 } else { \
64 STR = TEST_YIN_MODULE_10(MOD_NAME, MOD_NAME, "urn:libyang:test:"MOD_NAME, CONTENT); \
65 } \
66 } else { /* YANG */ \
67 if (RFC7950) { \
68 STR = TEST_YANG_MODULE_11(MOD_NAME, MOD_NAME, "urn:libyang:test:"MOD_NAME, CONTENT); \
69 } else { \
70 STR = TEST_YANG_MODULE_10(MOD_NAME, MOD_NAME, "urn:libyang:test:"MOD_NAME, CONTENT); \
71 } \
72 }
73
74#define TEST_SCHEMA_OK(RFC7950, YIN, MOD_NAME, CONTENT, RESULT) \
75 { \
76 const char *test_str__; \
77 TEST_SCHEMA_STR(RFC7950, YIN, MOD_NAME, CONTENT, test_str__) \
78 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, test_str__, YIN ? LYS_IN_YIN : LYS_IN_YANG, &(RESULT))); \
79 }
80
81#define TEST_SCHEMA_ERR(RFC7950, YIN, MOD_NAME, CONTENT, ERRMSG, ERRPATH) \
82 { \
83 const char *test_str__; \
84 TEST_SCHEMA_STR(RFC7950, YIN, MOD_NAME, CONTENT, test_str__) \
85 assert_int_not_equal(lys_parse_mem(UTEST_LYCTX, test_str__, YIN ? LYS_IN_YIN : LYS_IN_YANG, NULL), LY_SUCCESS); \
86 CHECK_LOG_CTX(ERRMSG, ERRPATH); \
87 }
88
89#define TEST_SCHEMA_PARSE_ERR(RFC7950, YIN, MOD_NAME, CONTENT, ERRMSG, ERRPATH) \
90 { \
91 const char *test_str__; \
92 TEST_SCHEMA_STR(RFC7950, YIN, MOD_NAME, CONTENT, test_str__) \
93 assert_int_not_equal(lys_parse_mem(UTEST_LYCTX, test_str__, YIN ? LYS_IN_YIN : LYS_IN_YANG, NULL), LY_SUCCESS); \
94 CHECK_LOG_CTX("Parsing module \""MOD_NAME"\" failed.", NULL, ERRMSG, ERRPATH); \
95 }
96
97#define TEST_STMT_DUP(RFC7950, YIN, STMT, MEMBER, VALUE1, VALUE2, LINE) \
98 if (YIN) { \
99 TEST_SCHEMA_PARSE_ERR(RFC7950, YIN, "dup", "", "Duplicate keyword \""MEMBER"\".", "Line number "LINE"."); \
100 } else { \
101 TEST_SCHEMA_PARSE_ERR(RFC7950, YIN, "dup", STMT"{"MEMBER" "VALUE1";"MEMBER" "VALUE2";}", \
102 "Duplicate keyword \""MEMBER"\".", "Line number "LINE"."); \
103 }
104
105#define TEST_STMT_SUBSTM_ERR(RFC7950, STMT, SUBSTMT, VALUE) ;\
106 TEST_SCHEMA_PARSE_ERR(RFC7950, 0, "inv", STMT" test {"SUBSTMT" "VALUE";}", \
107 "Invalid keyword \""SUBSTMT"\" as a child of \""STMT"\".", "Line number 1.");
108
109struct module_clb_list {
110 const char *name;
111 const char *data;
112};
113
114static LY_ERR
115module_clb(const char *mod_name, const char *UNUSED(mod_rev), const char *submod_name,
116 const char *UNUSED(sub_rev), void *user_data, LYS_INFORMAT *format,
117 const char **module_data, void (**free_module_data)(void *model_data, void *user_data))
118{
119 struct module_clb_list *list = (struct module_clb_list *)user_data;
120
121 for (unsigned int i = 0; list[i].data; i++) {
122
123 if ((submod_name && !strcmp(list[i].name, submod_name)) ||
124 (!submod_name && mod_name && !strcmp(list[i].name, mod_name))) {
125 *module_data = list[i].data;
126 *format = LYS_IN_YANG;
127 *free_module_data = NULL;
128 return LY_SUCCESS;
129 }
130 }
131 return LY_EINVAL;
132}
133
134static void
135test_getnext(void **state)
136{
137 struct lys_module *mod;
138 const struct lysc_node *node = NULL, *four;
139 const struct lysc_node_container *cont;
140 const struct lysc_action *rpc;
141
142 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module a {yang-version 1.1; namespace urn:a;prefix a;"
143 "container a { container one {presence test;} leaf two {type string;} leaf-list three {type string;}"
144 " list four {config false;} choice x { leaf five {type string;} case y {leaf six {type string;}}}"
145 " anyxml seven; action eight {input {leaf eight-input {type string;}} output {leaf eight-output {type string;}}}"
146 " notification nine {leaf nine-data {type string;}}}"
147 "leaf b {type string;} leaf-list c {type string;} list d {config false;}"
148 "choice x { case empty-x { choice empty-xc { case nothing;}} leaf e {type string;} case y {leaf f {type string;}}} anyxml g;"
149 "rpc h {input {leaf h-input {type string;}} output {leaf h-output {type string;}}}"
150 "rpc i;"
151 "notification j {leaf i-data {type string;}}"
152 "notification k;}", LYS_IN_YANG, &mod));
153 assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
154 assert_string_equal("a", node->name);
155 cont = (const struct lysc_node_container *)node;
156 assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
157 assert_string_equal("b", node->name);
158 assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
159 assert_string_equal("c", node->name);
160 assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
161 assert_string_equal("d", node->name);
162 assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
163 assert_string_equal("e", node->name);
164 assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
165 assert_string_equal("f", node->name);
166 assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
167 assert_string_equal("g", node->name);
168 assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
169 assert_string_equal("h", node->name);
170 rpc = (const struct lysc_action *)node;
171 assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
172 assert_string_equal("i", node->name);
173 assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
174 assert_string_equal("j", node->name);
175 assert_non_null(node = lys_getnext(node, NULL, mod->compiled, 0));
176 assert_string_equal("k", node->name);
177 assert_null(node = lys_getnext(node, NULL, mod->compiled, 0));
178 /* Inside container */
179 assert_non_null(node = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, 0));
180 assert_string_equal("one", node->name);
181 assert_non_null(node = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, 0));
182 assert_string_equal("two", node->name);
183 assert_non_null(node = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, 0));
184 assert_string_equal("three", node->name);
185 assert_non_null(node = four = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, 0));
186 assert_string_equal("four", node->name);
187 assert_non_null(node = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, 0));
188 assert_string_equal("five", node->name);
189 assert_non_null(node = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, 0));
190 assert_string_equal("six", node->name);
191 assert_non_null(node = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, 0));
192 assert_string_equal("seven", node->name);
193 assert_non_null(node = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, 0));
194 assert_string_equal("eight", node->name);
195 assert_non_null(node = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, 0));
196 assert_string_equal("nine", node->name);
197 assert_null(node = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, 0));
198 /* Inside RPC */
199 assert_non_null(node = lys_getnext(node, (const struct lysc_node *)rpc, mod->compiled, 0));
200 assert_string_equal("h-input", node->name);
201 assert_null(node = lys_getnext(node, (const struct lysc_node *)rpc, mod->compiled, 0));
202
203 /* options */
204 assert_non_null(node = lys_getnext(four, (const struct lysc_node *)cont, mod->compiled, LYS_GETNEXT_WITHCHOICE));
205 assert_string_equal("x", node->name);
206 assert_non_null(node = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, LYS_GETNEXT_WITHCHOICE));
207 assert_string_equal("seven", node->name);
208
209 assert_non_null(node = lys_getnext(four, (const struct lysc_node *)cont, mod->compiled, LYS_GETNEXT_NOCHOICE));
210 assert_string_equal("seven", node->name);
211
212 assert_non_null(node = lys_getnext(four, (const struct lysc_node *)cont, mod->compiled, LYS_GETNEXT_WITHCASE));
213 assert_string_equal("five", node->name);
214 assert_non_null(node = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, LYS_GETNEXT_WITHCASE));
215 assert_string_equal("y", node->name);
216 assert_non_null(node = lys_getnext(node, (const struct lysc_node *)cont, mod->compiled, LYS_GETNEXT_WITHCASE));
217 assert_string_equal("seven", node->name);
218
219 assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, LYS_GETNEXT_INTONPCONT));
220 assert_string_equal("one", node->name);
221
222 assert_non_null(node = lys_getnext(NULL, (const struct lysc_node *)rpc, mod->compiled, LYS_GETNEXT_OUTPUT));
223 assert_string_equal("h-output", node->name);
224 assert_null(node = lys_getnext(node, (const struct lysc_node *)rpc, mod->compiled, LYS_GETNEXT_OUTPUT));
225
226 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module c {namespace urn:c;prefix c; rpc c;}", LYS_IN_YANG, &mod));
227 assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, 0));
228 assert_string_equal("c", node->name);
229 assert_null(node = lys_getnext(node, NULL, mod->compiled, 0));
230
231 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module d {namespace urn:d;prefix d; notification d;}", LYS_IN_YANG, &mod));
232 assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, 0));
233 assert_string_equal("d", node->name);
234 assert_null(node = lys_getnext(node, NULL, mod->compiled, 0));
235
236 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, "module e {namespace urn:e;prefix e; container c {container cc;} leaf a {type string;}}", LYS_IN_YANG, &mod));
237 assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, 0));
238 assert_string_equal("c", node->name);
239 assert_non_null(node = lys_getnext(NULL, NULL, mod->compiled, LYS_GETNEXT_INTONPCONT));
240 assert_string_equal("a", node->name);
241}
242
243static void
244test_date(void **state)
245{
246 assert_int_equal(LY_EINVAL, lysp_check_date(NULL, NULL, 0, "date"));
247 CHECK_LOG("Invalid argument date (lysp_check_date()).", NULL);
248 assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "x", 1, "date"));
249 CHECK_LOG("Invalid argument date_len (lysp_check_date()).", NULL);
250 assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "nonsencexx", 10, "date"));
251 CHECK_LOG("Invalid value \"nonsencexx\" of \"date\".", NULL);
252 assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "123x-11-11", 10, "date"));
253 CHECK_LOG("Invalid value \"123x-11-11\" of \"date\".", NULL);
254 assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018-13-11", 10, "date"));
255 CHECK_LOG("Invalid value \"2018-13-11\" of \"date\".", NULL);
256 assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018-11-41", 10, "date"));
257 CHECK_LOG("Invalid value \"2018-11-41\" of \"date\".", NULL);
258 assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018-02-29", 10, "date"));
259 CHECK_LOG("Invalid value \"2018-02-29\" of \"date\".", NULL);
260 assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018.02-28", 10, "date"));
261 CHECK_LOG("Invalid value \"2018.02-28\" of \"date\".", NULL);
262 assert_int_equal(LY_EINVAL, lysp_check_date(NULL, "2018-02.28", 10, "date"));
263 CHECK_LOG("Invalid value \"2018-02.28\" of \"date\".", NULL);
264
265 assert_int_equal(LY_SUCCESS, lysp_check_date(NULL, "2018-11-11", 10, "date"));
266 assert_int_equal(LY_SUCCESS, lysp_check_date(NULL, "2018-02-28", 10, "date"));
267 assert_int_equal(LY_SUCCESS, lysp_check_date(NULL, "2016-02-29", 10, "date"));
268}
269
270static void
271test_revisions(void **state)
272{
273 struct lysp_revision *revs = NULL, *rev;
274
275 /* no error, it just does nothing */
276 lysp_sort_revisions(NULL);
277 CHECK_LOG(NULL, NULL);
278
279 /* revisions are stored in wrong order - the newest is the last */
280 LY_ARRAY_NEW_RET(NULL, revs, rev, );
281 strcpy(rev->date, "2018-01-01");
282 LY_ARRAY_NEW_RET(NULL, revs, rev, );
283 strcpy(rev->date, "2018-12-31");
284
285 assert_int_equal(2, LY_ARRAY_COUNT(revs));
286 assert_string_equal("2018-01-01", &revs[0]);
287 assert_string_equal("2018-12-31", &revs[1]);
288 /* the order should be fixed, so the newest revision will be the first in the array */
289 lysp_sort_revisions(revs);
290 assert_string_equal("2018-12-31", &revs[0]);
291 assert_string_equal("2018-01-01", &revs[1]);
292
293 LY_ARRAY_FREE(revs);
294}
295
296static void
297test_collision_typedef(void **state)
298{
299 const char *str;
300 char *submod;
301 struct module_clb_list list[3] = {0};
302
303 list[0].name = "asub";
304 list[1].name = "bsub";
305
306 /* collision with a built-in type */
307 str = "module a {namespace urn:a; prefix a; typedef binary {type string;}}";
308 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
309 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
310 "Duplicate identifier \"binary\" of typedef statement - name collision with a built-in type.", NULL);
311 str = "module a {namespace urn:a; prefix a; typedef bits {type string;}}";
312 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
313 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
314 "Duplicate identifier \"bits\" of typedef statement - name collision with a built-in type.", NULL);
315 str = "module a {namespace urn:a; prefix a; typedef boolean {type string;}}";
316 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
317 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
318 "Duplicate identifier \"boolean\" of typedef statement - name collision with a built-in type.", NULL);
319 str = "module a {namespace urn:a; prefix a; typedef decimal64 {type string;}}";
320 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
321 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
322 "Duplicate identifier \"decimal64\" of typedef statement - name collision with a built-in type.", NULL);
323 str = "module a {namespace urn:a; prefix a; typedef empty {type string;}}";
324 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
325 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
326 "Duplicate identifier \"empty\" of typedef statement - name collision with a built-in type.", NULL);
327 str = "module a {namespace urn:a; prefix a; typedef enumeration {type string;}}";
328 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
329 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
330 "Duplicate identifier \"enumeration\" of typedef statement - name collision with a built-in type.", NULL);
331 str = "module a {namespace urn:a; prefix a; typedef int8 {type string;}}";
332 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
333 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
334 "Duplicate identifier \"int8\" of typedef statement - name collision with a built-in type.", NULL);
335 str = "module a {namespace urn:a; prefix a; typedef int16 {type string;}}";
336 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
337 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
338 "Duplicate identifier \"int16\" of typedef statement - name collision with a built-in type.", NULL);
339 str = "module a {namespace urn:a; prefix a; typedef int32 {type string;}}";
340 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
341 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
342 "Duplicate identifier \"int32\" of typedef statement - name collision with a built-in type.", NULL);
343 str = "module a {namespace urn:a; prefix a; typedef int64 {type string;}}";
344 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
345 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
346 "Duplicate identifier \"int64\" of typedef statement - name collision with a built-in type.", NULL);
347 str = "module a {namespace urn:a; prefix a; typedef instance-identifier {type string;}}";
348 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
349 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
350 "Duplicate identifier \"instance-identifier\" of typedef statement - name collision with a built-in type.", NULL);
351 str = "module a {namespace urn:a; prefix a; typedef identityref {type string;}}";
352 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
353 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
354 "Duplicate identifier \"identityref\" of typedef statement - name collision with a built-in type.", NULL);
355 str = "module a {namespace urn:a; prefix a; typedef leafref {type string;}}";
356 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
357 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
358 "Duplicate identifier \"leafref\" of typedef statement - name collision with a built-in type.", NULL);
359 str = "module a {namespace urn:a; prefix a; typedef string {type int8;}}";
360 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
361 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
362 "Duplicate identifier \"string\" of typedef statement - name collision with a built-in type.", NULL);
363 str = "module a {namespace urn:a; prefix a; typedef union {type string;}}";
364 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
365 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
366 "Duplicate identifier \"union\" of typedef statement - name collision with a built-in type.", NULL);
367 str = "module a {namespace urn:a; prefix a; typedef uint8 {type string;}}";
368 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
369 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
370 "Duplicate identifier \"uint8\" of typedef statement - name collision with a built-in type.", NULL);
371 str = "module a {namespace urn:a; prefix a; typedef uint16 {type string;}}";
372 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
373 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
374 "Duplicate identifier \"uint16\" of typedef statement - name collision with a built-in type.", NULL);
375 str = "module a {namespace urn:a; prefix a; typedef uint32 {type string;}}";
376 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
377 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
378 "Duplicate identifier \"uint32\" of typedef statement - name collision with a built-in type.", NULL);
379 str = "module a {namespace urn:a; prefix a; typedef uint64 {type string;}}";
380 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
381 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
382 "Duplicate identifier \"uint64\" of typedef statement - name collision with a built-in type.", NULL);
383
384 str = "module mytypes {namespace urn:types; prefix t; typedef binary_ {type string;} typedef bits_ {type string;} typedef boolean_ {type string;} "
385 "typedef decimal64_ {type string;} typedef empty_ {type string;} typedef enumeration_ {type string;} typedef int8_ {type string;} typedef int16_ {type string;}"
386 "typedef int32_ {type string;} typedef int64_ {type string;} typedef instance-identifier_ {type string;} typedef identityref_ {type string;}"
387 "typedef leafref_ {type string;} typedef string_ {type int8;} typedef union_ {type string;} typedef uint8_ {type string;} typedef uint16_ {type string;}"
388 "typedef uint32_ {type string;} typedef uint64_ {type string;}}";
389 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
390
391 /* collision in node's scope */
392 str = "module a {namespace urn:a; prefix a; container c {typedef y {type int8;} typedef y {type string;}}}";
393 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
394 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
395 "Duplicate identifier \"y\" of typedef statement - name collision with sibling type.", NULL);
396
397 /* collision with parent node */
398 str = "module a {namespace urn:a; prefix a; container c {container d {typedef y {type int8;}} typedef y {type string;}}}";
399 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
400 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
401 "Duplicate identifier \"y\" of typedef statement - name collision with another scoped type.", NULL);
402
403 /* collision with module's top-level */
404 str = "module a {namespace urn:a; prefix a; typedef x {type string;} container c {typedef x {type int8;}}}";
405 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
406 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
407 "Duplicate identifier \"x\" of typedef statement - scoped type collide with a top-level type.", NULL);
408
409 /* collision of submodule's node with module's top-level */
410 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule b {belongs-to a {prefix a;} container c {typedef x {type string;}}}");
411 str = "module a {namespace urn:a; prefix a; include b; typedef x {type int8;}}";
412 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
413 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
414 "Duplicate identifier \"x\" of typedef statement - scoped type collide with a top-level type.", NULL);
415
416 /* collision of module's node with submodule's top-level */
417 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule b {belongs-to a {prefix a;} typedef x {type int8;}}");
418 str = "module a {namespace urn:a; prefix a; include b; container c {typedef x {type string;}}}";
419 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
420 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
421 "Duplicate identifier \"x\" of typedef statement - scoped type collide with a top-level type.", NULL);
422
423 /* collision of submodule's node with another submodule's top-level */
424 str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; include bsub;}";
425 list[0].data = "submodule asub {belongs-to a {prefix a;} typedef g {type int;}}";
426 list[1].data = "submodule bsub {belongs-to a {prefix a;} container c {typedef g {type int;}}}";
427 ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
428 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
429 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
430 "Duplicate identifier \"g\" of typedef statement - scoped type collide with a top-level type.", NULL);
431
432 /* collision of module's top-levels */
433 str = "module a {namespace urn:a; prefix a; typedef test {type string;} typedef test {type int8;}}";
434 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
435 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
436 "Duplicate identifier \"test\" of typedef statement - name collision with another top-level type.", NULL);
437
438 /* collision of submodule's top-levels */
439 submod = "submodule asub {belongs-to a {prefix a;} typedef g {type int;} typedef g {type int;}}";
440 str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub;}";
441 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod);
442 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
443 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
444 "Duplicate identifier \"g\" of typedef statement - name collision with another top-level type.", NULL);
445
446 /* collision of module's top-level with submodule's top-levels */
447 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule b {belongs-to a {prefix a;} typedef x {type string;}}");
448 str = "module a {namespace urn:a; prefix a; include b; typedef x {type int8;}}";
449 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
450 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
451 "Duplicate identifier \"x\" of typedef statement - name collision with another top-level type.", NULL);
452
453 /* collision of submodule's top-level with another submodule's top-levels */
454 str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; include bsub;}";
455 list[0].data = "submodule asub {belongs-to a {prefix a;} typedef g {type int;}}";
456 list[1].data = "submodule bsub {belongs-to a {prefix a;} typedef g {type int;}}";
457 ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
458 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
459 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
460 "Duplicate identifier \"g\" of typedef statement - name collision with another top-level type.", NULL);
461
462 /* error in type-stmt */
463 str = "module a {namespace urn:a; prefix a; container c {typedef x {type t{}}";
464 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
465 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
466 "Unexpected end-of-input.", "Line number 1.");
467 UTEST_LOG_CLEAN;
468
469 /* no collision if the same names are in different scope */
470 str = "module a {yang-version 1.1; namespace urn:a; prefix a;"
471 "container c {typedef g {type int;}} container d {typedef g {type int;}}}";
472 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
473}
474
475static void
476test_collision_grouping(void **state)
477{
478 const char *str;
479 char *submod;
480 struct module_clb_list list[3] = {0};
481
482 list[0].name = "asub";
483 list[1].name = "bsub";
484
485 /* collision in node's scope */
486 str = "module a {namespace urn:a; prefix a; container c {grouping y; grouping y;}}";
487 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
488 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
489 "Duplicate identifier \"y\" of grouping statement - name collision with sibling grouping.", NULL);
490
491 /* collision with parent node */
492 str = "module a {namespace urn:a; prefix a; container c {container d {grouping y;} grouping y;}}";
493 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
494 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
495 "Duplicate identifier \"y\" of grouping statement - name collision with another scoped grouping.", NULL);
496
497 /* collision with module's top-level */
498 str = "module a {namespace urn:a; prefix a; grouping x; container c {grouping x;}}";
499 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
500 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
501 "Duplicate identifier \"x\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
502
503 /* collision of submodule's node with module's top-level */
504 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule b {belongs-to a {prefix a;} container c {grouping x;}}");
505 str = "module a {namespace urn:a; prefix a; include b; grouping x;}";
506 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
507 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
508 "Duplicate identifier \"x\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
509
510 /* collision of module's node with submodule's top-level */
511 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule b {belongs-to a {prefix a;} grouping x;}");
512 str = "module a {namespace urn:a; prefix a; include b; container c {grouping x;}}";
513 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
514 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
515 "Duplicate identifier \"x\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
516
517 /* collision of submodule's node with another submodule's top-level */
518 str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; include bsub;}";
519 list[0].data = "submodule asub {belongs-to a {prefix a;} grouping g;}";
520 list[1].data = "submodule bsub {belongs-to a {prefix a;} container c {grouping g;}}";
521 ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
522 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
523 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
524 "Duplicate identifier \"g\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
525
526 /* collision of module's top-levels */
527 str = "module a {namespace urn:a; prefix a; grouping test; grouping test;}";
528 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
529 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
530 "Duplicate identifier \"test\" of grouping statement - name collision with another top-level grouping.", NULL);
531
532 /* collision of submodule's top-levels */
533 submod = "submodule asub {belongs-to a {prefix a;} grouping g; grouping g;}";
534 str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub;}";
535 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod);
536 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
537 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
538 "Duplicate identifier \"g\" of grouping statement - name collision with another top-level grouping.", NULL);
539
540 /* collision of module's top-level with submodule's top-levels */
541 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule b {belongs-to a {prefix a;} grouping x;}");
542 str = "module a {namespace urn:a; prefix a; include b; grouping x;}";
543 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
544 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
545 "Duplicate identifier \"x\" of grouping statement - name collision with another top-level grouping.", NULL);
546
547 /* collision of submodule's top-level with another submodule's top-levels */
548 str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; include bsub;}";
549 list[0].data = "submodule asub {belongs-to a {prefix a;} grouping g;}";
550 list[1].data = "submodule bsub {belongs-to a {prefix a;} grouping g;}";
551 ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
552 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
553 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
554 "Duplicate identifier \"g\" of grouping statement - name collision with another top-level grouping.", NULL);
555
556 /* collision in nested groupings, top-level */
557 str = "module a {namespace urn:a; prefix a; grouping g {grouping g;}}";
558 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
559 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
560 "Duplicate identifier \"g\" of grouping statement - scoped grouping collide with a top-level grouping.", NULL);
561
562 /* collision in nested groupings, in node */
563 str = "module a {namespace urn:a; prefix a; container c {grouping g {grouping g;}}}";
564 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
565 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
566 "Duplicate identifier \"g\" of grouping statement - name collision with another scoped grouping.", NULL);
567
568 /* no collision if the same names are in different scope */
569 str = "module a {yang-version 1.1; namespace urn:a; prefix a;"
570 "container c {grouping g;} container d {grouping g;}}";
571 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
572}
573
574static void
575test_collision_identity(void **state)
576{
577 const char *str;
578 char *submod;
579 struct module_clb_list list[3] = {0};
580
581 list[0].name = "asub";
582 list[1].name = "bsub";
583
584 /* collision of module's top-levels */
585 str = "module a {yang-version 1.1; namespace urn:a; prefix a; identity g; identity g;}";
586 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
587 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
588 "Duplicate identifier \"g\" of identity statement - name collision with another top-level identity.", NULL);
589
590 /* collision of submodule's top-levels */
591 submod = "submodule asub {belongs-to a {prefix a;} identity g; identity g;}";
592 str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub;}";
593 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod);
594 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
595 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
596 "Duplicate identifier \"g\" of identity statement - name collision with another top-level identity.", NULL);
597
598 /* collision of module's top-level with submodule's top-levels */
599 submod = "submodule asub {belongs-to a {prefix a;} identity g;}";
600 str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; identity g;}";
601 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod);
602 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
603 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
604 "Duplicate identifier \"g\" of identity statement - name collision with another top-level identity.", NULL);
605
606 /* collision of submodule's top-level with another submodule's top-levels */
607 str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; include bsub;}";
608 list[0].data = "submodule asub {belongs-to a {prefix a;} identity g;}";
609 list[1].data = "submodule bsub {belongs-to a {prefix a;} identity g;}";
610 ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
611 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
612 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
613 "Duplicate identifier \"g\" of identity statement - name collision with another top-level identity.", NULL);
614}
615
616static void
617test_collision_feature(void **state)
618{
619 const char *str;
620 char *submod;
621 struct module_clb_list list[3] = {0};
622
623 list[0].name = "asub";
624 list[1].name = "bsub";
625
626 /* collision of module's top-levels */
627 str = "module a {yang-version 1.1; namespace urn:a; prefix a; feature g; feature g;}";
628 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
629 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
630 "Duplicate identifier \"g\" of feature statement - name collision with another top-level feature.", NULL);
631
632 /* collision of submodule's top-levels */
633 submod = "submodule asub {belongs-to a {prefix a;} feature g; feature g;}";
634 str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub;}";
635 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod);
636 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
637 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
638 "Duplicate identifier \"g\" of feature statement - name collision with another top-level feature.", NULL);
639
640 /* collision of module's top-level with submodule's top-levels */
641 submod = "submodule asub {belongs-to a {prefix a;} feature g;}";
642 str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; feature g;}";
643 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, submod);
644 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
645 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
646 "Duplicate identifier \"g\" of feature statement - name collision with another top-level feature.", NULL);
647
648 /* collision of submodule's top-level with another submodule's top-levels */
649 str = "module a {yang-version 1.1; namespace urn:a; prefix a; include asub; include bsub;}";
650 list[0].data = "submodule asub {belongs-to a {prefix a;} feature g;}";
651 list[1].data = "submodule bsub {belongs-to a {prefix a;} feature g;}";
652 ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
653 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL));
654 CHECK_LOG_CTX("Parsing module \"a\" failed.", NULL,
655 "Duplicate identifier \"g\" of feature statement - name collision with another top-level feature.", NULL);
656}
657
658static void
659test_accessible_tree(void **state)
660{
661 const char *str;
662
663 /* config -> config */
664 str = "module a {\n"
665 " namespace urn:a;\n"
666 " prefix a;\n"
667 " container cont {\n"
668 " leaf l {\n"
669 " type empty;\n"
670 " }\n"
671 " }\n"
672 " container cont2 {\n"
673 " leaf l2 {\n"
674 " must ../../cont/l;\n"
675 " type leafref {\n"
676 " path /cont/l;\n"
677 " }\n"
678 " }\n"
679 " }\n"
680 "}";
681 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
682 CHECK_LOG_CTX(NULL, NULL);
683
684 /* config -> state leafref */
685 str = "module b {\n"
686 " namespace urn:b;\n"
687 " prefix b;\n"
688 " container cont {\n"
689 " config false;\n"
690 " leaf l {\n"
691 " type empty;\n"
692 " }\n"
693 " }\n"
694 " container cont2 {\n"
695 " leaf l2 {\n"
696 " type leafref {\n"
697 " path /cont/l;\n"
698 " }\n"
699 " }\n"
700 " }\n"
701 "}";
702 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
703 CHECK_LOG_CTX("Invalid leafref path \"/cont/l\" - target is supposed to represent configuration data"
704 " (as the leafref does), but it does not.", "Schema location \"/b:cont2/l2\".");
705
706 /* config -> state must */
707 str = "module b {\n"
708 " namespace urn:b;\n"
709 " prefix b;\n"
710 " container cont {\n"
711 " config false;\n"
712 " leaf l {\n"
713 " type empty;\n"
714 " }\n"
715 " }\n"
716 " container cont2 {\n"
717 " leaf l2 {\n"
718 " must ../../cont/l;\n"
719 " type empty;\n"
720 " }\n"
721 " }\n"
722 "}";
723 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
724 CHECK_LOG_CTX("Schema node \"cont\" for parent \"<config-root>\" not found; in expr \"../../cont\" "
725 "with context node \"/b:cont2/l2\".", NULL);
726
727 /* state -> config */
728 str = "module c {\n"
729 " namespace urn:c;\n"
730 " prefix c;\n"
731 " container cont {\n"
732 " leaf l {\n"
733 " type empty;\n"
734 " }\n"
735 " }\n"
736 " container cont2 {\n"
737 " config false;\n"
738 " leaf l2 {\n"
739 " must ../../cont/l;\n"
740 " type leafref {\n"
741 " path /cont/l;\n"
742 " }\n"
743 " }\n"
744 " }\n"
745 "}";
746 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
747 CHECK_LOG_CTX(NULL, NULL);
748
749 /* notif -> state */
750 str = "module d {\n"
751 " namespace urn:d;\n"
752 " prefix d;\n"
753 " container cont {\n"
754 " config false;\n"
755 " leaf l {\n"
756 " type empty;\n"
757 " }\n"
758 " }\n"
759 " notification notif {\n"
760 " leaf l2 {\n"
761 " must ../../cont/l;\n"
762 " type leafref {\n"
763 " path /cont/l;\n"
764 " }\n"
765 " }\n"
766 " }\n"
767 "}";
768 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
769 CHECK_LOG_CTX(NULL, NULL);
770
771 /* notif -> notif */
772 str = "module e {\n"
773 " namespace urn:e;\n"
774 " prefix e;\n"
775 " notification notif {\n"
776 " leaf l {\n"
777 " type empty;\n"
778 " }\n"
779 " leaf l2 {\n"
780 " must ../../notif/l;\n"
781 " type leafref {\n"
782 " path /notif/l;\n"
783 " }\n"
784 " }\n"
785 " }\n"
786 "}";
787 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
788 CHECK_LOG_CTX(NULL, NULL);
789
790 /* rpc input -> state */
791 str = "module f {\n"
792 " namespace urn:f;\n"
793 " prefix f;\n"
794 " container cont {\n"
795 " config false;\n"
796 " leaf l {\n"
797 " type empty;\n"
798 " }\n"
799 " }\n"
800 " rpc rp {\n"
801 " input {\n"
802 " leaf l2 {\n"
803 " must ../../cont/l;\n"
804 " type leafref {\n"
805 " path /cont/l;\n"
806 " }\n"
807 " }\n"
808 " }\n"
809 " }\n"
810 "}";
811 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
812 CHECK_LOG_CTX(NULL, NULL);
813
814 /* rpc input -> rpc input */
815 str = "module g {\n"
816 " namespace urn:g;\n"
817 " prefix g;\n"
818 " rpc rp {\n"
819 " input {\n"
820 " leaf l {\n"
821 " type empty;\n"
822 " }\n"
823 " leaf l2 {\n"
824 " must ../l;\n"
825 " type leafref {\n"
826 " path /rp/l;\n"
827 " }\n"
828 " }\n"
829 " }\n"
830 " }\n"
831 "}";
832 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
833 CHECK_LOG_CTX(NULL, NULL);
834
835 /* rpc input -> rpc output leafref */
836 str = "module h {\n"
837 " namespace urn:h;\n"
838 " prefix h;\n"
839 " rpc rp {\n"
840 " input {\n"
841 " leaf l2 {\n"
842 " type leafref {\n"
843 " path /rp/l;\n"
844 " }\n"
845 " }\n"
846 " }\n"
847 " output {\n"
848 " leaf l {\n"
849 " type empty;\n"
850 " }\n"
851 " }\n"
852 " }\n"
853 "}";
854 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
855 CHECK_LOG_CTX("Not found node \"l\" in path.", "Schema location \"/h:rp/input/l2\".");
856
857 /* rpc input -> rpc output must */
858 str = "module h {\n"
859 " namespace urn:h;\n"
860 " prefix h;\n"
861 " rpc rp {\n"
862 " input {\n"
863 " leaf l2 {\n"
864 " must ../l;\n"
865 " type empty;\n"
866 " }\n"
867 " }\n"
868 " output {\n"
869 " leaf l {\n"
870 " type empty;\n"
871 " }\n"
872 " }\n"
873 " }\n"
874 "}";
875 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
876 CHECK_LOG_CTX("Schema node \"l\" for parent \"/h:rp\" not found; in expr \"../l\" with context node \"/h:rp/input/l2\".", NULL);
877
878 /* rpc input -> notif leafref */
879 str = "module i {\n"
880 " namespace urn:i;\n"
881 " prefix i;\n"
882 " rpc rp {\n"
883 " input {\n"
884 " leaf l2 {\n"
885 " type leafref {\n"
886 " path ../../notif/l;\n"
887 " }\n"
888 " }\n"
889 " }\n"
890 " }\n"
891 " notification notif {\n"
892 " leaf l {\n"
893 " type empty;\n"
894 " }\n"
895 " }\n"
896 "}";
897 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
898 CHECK_LOG_CTX("Not found node \"notif\" in path.", "Schema location \"/i:rp/input/l2\".");
899
900 /* rpc input -> notif must */
901 str = "module i {\n"
902 " namespace urn:i;\n"
903 " prefix i;\n"
904 " rpc rp {\n"
905 " input {\n"
906 " leaf l2 {\n"
907 " must /notif/l;\n"
908 " type empty;\n"
909 " }\n"
910 " }\n"
911 " }\n"
912 " notification notif {\n"
913 " leaf l {\n"
914 " type empty;\n"
915 " }\n"
916 " }\n"
917 "}";
918 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
919 CHECK_LOG_CTX("Schema node \"notif\" for parent \"<root>\" not found; in expr \"/notif\" "
920 "with context node \"/i:rp/input/l2\".", NULL);
921
922 /* action output -> state */
923 str = "module j {\n"
924 " yang-version 1.1;\n"
925 " namespace urn:j;\n"
926 " prefix j;\n"
927 " container cont {\n"
928 " list ll {\n"
929 " key k;\n"
930 " leaf k {\n"
931 " type string;\n"
932 " }\n"
933 " action act {\n"
934 " output {\n"
935 " leaf l2 {\n"
936 " must /cont/l;\n"
937 " type leafref {\n"
938 " path ../../../l;\n"
939 " }\n"
940 " }\n"
941 " }\n"
942 " }\n"
943 " }\n"
944 " leaf l {\n"
945 " config false;\n"
946 " type empty;\n"
947 " }\n"
948 " }\n"
949 "}";
950 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
951 CHECK_LOG_CTX(NULL, NULL);
952
953 /* action output -> action input leafref */
954 str = "module k {\n"
955 " yang-version 1.1;\n"
956 " namespace urn:k;\n"
957 " prefix k;\n"
958 " container cont {\n"
959 " list ll {\n"
960 " key k;\n"
961 " leaf k {\n"
962 " type string;\n"
963 " }\n"
964 " action act {\n"
965 " input {\n"
966 " leaf l {\n"
967 " type empty;\n"
968 " }\n"
969 " }\n"
970 " output {\n"
971 " leaf l2 {\n"
972 " type leafref {\n"
973 " path ../l;\n"
974 " }\n"
975 " }\n"
976 " }\n"
977 " }\n"
978 " }\n"
979 " }\n"
980 "}";
981 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
982 CHECK_LOG_CTX("Not found node \"l\" in path.", "Schema location \"/k:cont/ll/act/output/l2\".");
983
984 /* action output -> action input must */
985 str = "module k {\n"
986 " yang-version 1.1;\n"
987 " namespace urn:k;\n"
988 " prefix k;\n"
989 " container cont {\n"
990 " list ll {\n"
991 " key k;\n"
992 " leaf k {\n"
993 " type string;\n"
994 " }\n"
995 " action act {\n"
996 " input {\n"
997 " leaf l {\n"
998 " type empty;\n"
999 " }\n"
1000 " }\n"
1001 " output {\n"
1002 " leaf l2 {\n"
1003 " must /cont/ll/act/l;\n"
1004 " type empty;\n"
1005 " }\n"
1006 " }\n"
1007 " }\n"
1008 " }\n"
1009 " }\n"
1010 "}";
1011 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_SUCCESS);
1012 CHECK_LOG_CTX("Schema node \"l\" for parent \"/k:cont/ll/act\" not found; in expr \"/cont/ll/act/l\" "
1013 "with context node \"/k:cont/ll/act/output/l2\".", NULL);
1014}
1015
1016static void
1017test_includes(void **state)
1018{
1019 struct lys_module *mod;
1020
1021 {
1022 /* YANG 1.0 - the missing include sub_a_two in main_a will be injected from sub_a_one */
1023 struct module_clb_list list[] = {
1024 {"main_a", "module main_a { namespace urn:test:main_a; prefix ma; include sub_a_one;}"},
1025 {"sub_a_one", "submodule sub_a_one { belongs-to main_a { prefix ma; } include sub_a_two;}"},
1026 {"sub_a_two", "submodule sub_a_two { belongs-to main_a { prefix ma; } }"},
1027 {NULL, NULL}
1028 };
1029
1030 ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
1031 mod = ly_ctx_load_module(UTEST_LYCTX, "main_a", NULL, NULL);
1032 assert_non_null(mod);
1033 assert_int_equal(2, LY_ARRAY_COUNT(mod->parsed->includes));
1034 assert_true(mod->parsed->includes[1].injected);
1035 }
1036
1037 {
1038 /* YANG 1.1 - the missing include sub_b_two in main_b is error */
1039 struct module_clb_list list[] = {
1040 {"main_b", "module main_b { yang-version 1.1; namespace urn:test:main_b; prefix mb; include sub_b_one;}"},
1041 {"sub_b_one", "submodule sub_b_one { yang-version 1.1; belongs-to main_b { prefix mb; } include sub_b_two;}"},
1042 {"sub_b_two", "submodule sub_b_two { yang-version 1.1; belongs-to main_b { prefix mb; } }"},
1043 {NULL, NULL}
1044 };
1045
1046 ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
1047 mod = ly_ctx_load_module(UTEST_LYCTX, "main_b", NULL, NULL);
1048 assert_null(mod);
1049 CHECK_LOG_CTX("Loading \"main_b\" module failed.", NULL,
1050 "Data model \"main_b\" not found in local searchdirs.", NULL,
1051 "Parsing module \"main_b\" failed.", NULL,
1052 "Including \"sub_b_one\" submodule into \"main_b\" failed.", NULL,
1053 "Data model \"sub_b_one\" not found in local searchdirs.", NULL,
1054 "Parsing submodule \"sub_b_one\" failed.", NULL,
1055 "YANG 1.1 requires all submodules to be included from main module. But submodule \"sub_b_one\" includes "
1056 "submodule \"sub_b_two\" which is not included by main module \"main_b\".", NULL,
1057 "YANG version 1.1 expects all includes in main module, includes in submodules (sub_b_one) are not necessary.", NULL);
1058 }
1059
1060 {
1061 /* YANG 1.1 - all includes are in main_c, includes in submodules are not necessary, so expect warning */
1062 struct module_clb_list list[] = {
1063 {"main_c", "module main_c { yang-version 1.1; namespace urn:test:main_c; prefix mc; include sub_c_one; include sub_c_two;}"},
1064 {"sub_c_one", "submodule sub_c_one { yang-version 1.1; belongs-to main_c { prefix mc; } include sub_c_two;}"},
1065 {"sub_c_two", "submodule sub_c_two { yang-version 1.1; belongs-to main_c { prefix mc; } include sub_c_one;}"},
1066 {NULL, NULL}
1067 };
1068
1069 ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list);
1070 mod = ly_ctx_load_module(UTEST_LYCTX, "main_c", NULL, NULL);
1071 assert_non_null(mod);
1072 assert_int_equal(2, LY_ARRAY_COUNT(mod->parsed->includes));
1073 assert_false(mod->parsed->includes[1].injected);
1074 /* result is ok, but log includes the warning */
1075 CHECK_LOG_CTX("YANG version 1.1 expects all includes in main module, includes in submodules (sub_c_two) are not necessary.", NULL);
1076 }
1077}
1078
1079static void
1080test_key_order(void **state)
1081{
1082 struct lys_module *mod;
1083 const struct lysc_node *node;
1084
1085 struct module_clb_list list1[] = {
1086 {"a", "module a {"
1087 "yang-version 1.1;"
1088 "namespace urn:test:a;"
1089 "prefix a;"
1090 "list l {"
1091 " key \"k1 k2\";"
1092 " leaf k2 {type string;}"
1093 " leaf k1 {type string;}"
1094 "}"
1095 "}"},
1096 {NULL, NULL}
1097 };
1098
1099 ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list1);
1100 mod = ly_ctx_load_module(UTEST_LYCTX, "a", NULL, NULL);
1101 assert_non_null(mod);
1102
1103 node = lysc_node_child(mod->compiled->data);
1104 assert_string_equal("k1", node->name);
1105 node = node->next;
1106 assert_string_equal("k2", node->name);
1107
1108 struct module_clb_list list2[] = {
1109 {"b", "module b {"
1110 "yang-version 1.1;"
1111 "namespace urn:test:b;"
1112 "prefix b;"
1113 "list l {"
1114 " key \"k1 k2 k3 k4\";"
1115 " leaf k4 {type string;}"
1116 " container c {"
1117 " leaf l1 {type string;}"
1118 " }"
1119 " leaf k2 {type string;}"
1120 " leaf l2 {type string;}"
1121 " leaf k1 {type string;}"
1122 " leaf k3 {type string;}"
1123 "}"
1124 "}"},
1125 {NULL, NULL}
1126 };
1127
1128 ly_ctx_set_module_imp_clb(UTEST_LYCTX, module_clb, list2);
1129 mod = ly_ctx_load_module(UTEST_LYCTX, "b", NULL, NULL);
1130 assert_non_null(mod);
1131
1132 node = lysc_node_child(mod->compiled->data);
1133 assert_string_equal("k1", node->name);
1134 node = node->next;
1135 assert_string_equal("k2", node->name);
1136 node = node->next;
1137 assert_string_equal("k3", node->name);
1138 node = node->next;
1139 assert_string_equal("k4", node->name);
1140}
1141
1142static void
1143test_disabled_enum(void **state)
1144{
1145 const char *str;
1146
1147 /* no enabled enum */
1148 str = "module a {"
1149 "yang-version 1.1;"
1150 "namespace urn:test:a;"
1151 "prefix a;"
1152 "feature f;"
1153 "leaf l {type enumeration {"
1154 " enum e1 {if-feature f;}"
1155 " enum e2 {if-feature f;}"
1156 "}}"
1157 "}";
1158 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
1159 CHECK_LOG_CTX("Enumeration type of node \"l\" without any (or all disabled) valid values.", "Schema location \"/a:l\".");
1160
1161 /* disabled default value */
1162 str = "module a {"
1163 "yang-version 1.1;"
1164 "namespace urn:test:a;"
1165 "prefix a;"
1166 "feature f;"
1167 "leaf l {"
1168 " type enumeration {"
1169 " enum e1 {if-feature f;}"
1170 " enum e2;"
1171 " }"
1172 " default e1;"
1173 "}"
1174 "}";
1175 assert_int_equal(lys_parse_mem(UTEST_LYCTX, str, LYS_IN_YANG, NULL), LY_EVALID);
1176 CHECK_LOG_CTX("Invalid default - value does not fit the type (Invalid enumeration value \"e1\".).",
1177 "Schema location \"/a:l\".");
1178}
1179
1180static void
1181test_identity(void **state)
1182{
1183 struct lys_module *mod, *mod_imp;
1184
1185 /*
1186 * parsing YANG
1187 */
1188 TEST_STMT_DUP(1, 0, "identity id", "description", "a", "b", "1");
1189 TEST_STMT_DUP(1, 0, "identity id", "reference", "a", "b", "1");
1190 TEST_STMT_DUP(1, 0, "identity id", "status", "current", "obsolete", "1");
1191
1192 /* full content */
1193 TEST_SCHEMA_OK(1, 0, "identityone",
1194 "identity test {base \"a\";base b; description text;reference \'another text\';status current; if-feature x;if-feature y; identityone:ext;}"
1195 "identity a; identity b; extension ext; feature x; feature y;", mod);
1196 assert_non_null(mod->parsed->identities);
1197 assert_int_equal(3, LY_ARRAY_COUNT(mod->parsed->identities));
1198
1199 /* invalid substatement */
1200 TEST_STMT_SUBSTM_ERR(0, "identity", "organization", "XXX");
1201
1202 /*
1203 * parsing YIN
1204 */
1205 /* max subelems */
1206 TEST_SCHEMA_OK(1, 1, "identityone-yin", "<identity name=\"ident-name\">"
1207 "<if-feature name=\"iff\"/>"
1208 "<base name=\"base-name\"/>"
1209 "<status value=\"deprecated\"/>"
1210 "<description><text>desc</text></description>"
1211 "<reference><text>ref</text></reference>"
1212 /* TODO yin-extension-prefix-compilation-bug "<myext:ext xmlns:myext=\"urn:libyang:test:identityone-yin\"/>" */
1213 "</identity><extension name=\"ext\"/><identity name=\"base-name\"/><feature name=\"iff\"/>", mod);
1214 assert_int_equal(2, LY_ARRAY_COUNT(mod->parsed->identities));
1215 assert_string_equal(mod->parsed->identities[0].name, "ident-name");
1216 assert_string_equal(mod->parsed->identities[0].bases[0], "base-name");
1217 assert_string_equal(mod->parsed->identities[0].iffeatures[0].str, "iff");
1218 assert_string_equal(mod->parsed->identities[0].dsc, "desc");
1219 assert_string_equal(mod->parsed->identities[0].ref, "ref");
1220 assert_true(mod->parsed->identities[0].flags & LYS_STATUS_DEPRC);
1221 /*assert_string_equal(mod->parsed->identities[0].exts[0].name, "ext");
1222 assert_non_null(mod->parsed->identities[0].exts[0].compiled);
1223 assert_int_equal(mod->parsed->identities[0].exts[0].yin, 1);
1224 assert_int_equal(mod->parsed->identities[0].exts[0].insubstmt_index, 0);
1225 assert_int_equal(mod->parsed->identities[0].exts[0].insubstmt, LYEXT_SUBSTMT_SELF);*/
1226
1227 /* min subelems */
1228 TEST_SCHEMA_OK(1, 1, "identitytwo-yin", "<identity name=\"ident-name\" />", mod);
1229 assert_int_equal(1, LY_ARRAY_COUNT(mod->parsed->identities));
1230 assert_string_equal(mod->parsed->identities[0].name, "ident-name");
1231
1232 /* invalid substatement */
1233 TEST_SCHEMA_PARSE_ERR(0, 1, "inv", "<identity name=\"ident-name\"><if-feature name=\"iff\"/></identity>",
1234 "Invalid sub-elemnt \"if-feature\" of \"identity\" element - "
1235 "this sub-element is allowed only in modules with version 1.1 or newer.", "Line number 1.");
1236
1237 /*
1238 * compiling
1239 */
1240 TEST_SCHEMA_OK(0, 0, "a", "identity a1;", mod_imp);
1241 TEST_SCHEMA_OK(1, 0, "b", "import a {prefix a;}"
1242 "identity b1; identity b2; identity b3 {base b1; base b:b2; base a:a1;}"
1243 "identity b4 {base b:b1; base b3;}", mod);
1244 assert_non_null(mod_imp->compiled);
1245 assert_non_null(mod_imp->identities);
1246 assert_non_null(mod->identities);
1247 assert_non_null(mod_imp->identities[0].derived);
1248 assert_int_equal(1, LY_ARRAY_COUNT(mod_imp->identities[0].derived));
1249 assert_ptr_equal(mod_imp->identities[0].derived[0], &mod->identities[2]);
1250 assert_non_null(mod->identities[0].derived);
1251 assert_int_equal(2, LY_ARRAY_COUNT(mod->identities[0].derived));
1252 assert_ptr_equal(mod->identities[0].derived[0], &mod->identities[2]);
1253 assert_ptr_equal(mod->identities[0].derived[1], &mod->identities[3]);
1254 assert_non_null(mod->identities[1].derived);
1255 assert_int_equal(1, LY_ARRAY_COUNT(mod->identities[1].derived));
1256 assert_ptr_equal(mod->identities[1].derived[0], &mod->identities[2]);
1257 assert_non_null(mod->identities[2].derived);
1258 assert_int_equal(1, LY_ARRAY_COUNT(mod->identities[2].derived));
1259 assert_ptr_equal(mod->identities[2].derived[0], &mod->identities[3]);
1260
1261 TEST_SCHEMA_OK(1, 0, "c", "identity c2 {base c1;} identity c1;", mod);
1262 assert_int_equal(1, LY_ARRAY_COUNT(mod->identities[1].derived));
1263 assert_ptr_equal(mod->identities[1].derived[0], &mod->identities[0]);
1264
1265 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule inv_sub {belongs-to inv {prefix inv;} identity i1;}");
1266 TEST_SCHEMA_ERR(0, 0, "inv", "identity i1 {base i2;}", "Unable to find base (i2) of identity \"i1\".", "/inv:{identity='i1'}");
1267 TEST_SCHEMA_ERR(0, 0, "inv", "identity i1 {base i1;}", "Identity \"i1\" is derived from itself.", "/inv:{identity='i1'}");
1268 TEST_SCHEMA_ERR(0, 0, "inv", "identity i1 {base i2;}identity i2 {base i3;}identity i3 {base i1;}",
1269 "Identity \"i1\" is indirectly derived from itself.", "/inv:{identity='i3'}");
1270
1271 /* base in non-implemented module */
1272 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb,
1273 "module base {namespace \"urn\"; prefix b; identity i1; identity i2 {base i1;}}");
1274 TEST_SCHEMA_OK(0, 0, "ident", "import base {prefix b;} identity ii {base b:i1;}", mod);
1275
1276 /* default value from non-implemented module */
1277 TEST_SCHEMA_ERR(0, 0, "ident2", "import base {prefix b;} leaf l {type identityref {base b:i1;} default b:i2;}",
1278 "Invalid default - value does not fit the type (Invalid identityref \"b:i2\" value"
1279 " - identity found in non-implemented module \"base\".).", "Schema location \"/ident2:l\".");
1280
1281 /* default value in typedef from non-implemented module */
1282 TEST_SCHEMA_ERR(0, 0, "ident2", "import base {prefix b;} typedef t1 {type identityref {base b:i1;} default b:i2;}"
1283 "leaf l {type t1;}", "Invalid default - value does not fit the type (Invalid"
1284 " identityref \"b:i2\" value - identity found in non-implemented module \"base\".).", "Schema location \"/ident2:l\".");
1285
1286 /*
1287 * printing
1288 */
1289
1290 /*
1291 * cleanup
1292 */
1293}
1294
1295static void
1296test_feature(void **state)
1297{
1298 struct lys_module *mod;
1299 const struct lysp_feature *f;
1300
1301 /*
1302 * parsing YANG
1303 */
1304
1305 TEST_STMT_DUP(1, 0, "feature f", "description", "a", "b", "1");
1306 TEST_STMT_DUP(1, 0, "feature f", "reference", "a", "b", "1");
1307 TEST_STMT_DUP(1, 0, "feature f", "status", "current", "obsolete", "1");
1308
1309 /* full content */
1310 TEST_SCHEMA_OK(1, 0, "featureone",
1311 "feature test {description text;reference \'another text\';status current; if-feature x; if-feature y; featureone:ext;}"
1312 "extension ext; feature x; feature y;", mod);
1313 assert_non_null(mod->parsed->features);
1314 assert_int_equal(3, LY_ARRAY_COUNT(mod->parsed->features));
1315
1316 /* invalid substatement */
1317 TEST_STMT_SUBSTM_ERR(0, "feature", "organization", "XXX");
1318
1319 /*
1320 * parsing YIN
1321 */
1322 /* max subelems */
1323 TEST_SCHEMA_OK(0, 1, "featureone-yin", "<feature name=\"feature-name\">"
1324 "<if-feature name=\"iff\"/>"
1325 "<status value=\"deprecated\"/>"
1326 "<description><text>desc</text></description>"
1327 "<reference><text>ref</text></reference>"
1328 /* TODO yin-extension-prefix-compilation-bug "<myext:ext xmlns:myext=\"urn:libyang:test:featureone-yin\"/>" */
1329 "</feature><extension name=\"ext\"/><feature name=\"iff\"/>", mod);
1330 assert_int_equal(2, LY_ARRAY_COUNT(mod->parsed->features));
1331 assert_string_equal(mod->parsed->features[0].name, "feature-name");
1332 assert_string_equal(mod->parsed->features[0].dsc, "desc");
1333 assert_true(mod->parsed->features[0].flags & LYS_STATUS_DEPRC);
1334 assert_string_equal(mod->parsed->features[0].iffeatures[0].str, "iff");
1335 assert_string_equal(mod->parsed->features[0].ref, "ref");
1336 /*assert_string_equal(mod->parsed->features[0].exts[0].name, "ext");
1337 assert_int_equal(mod->parsed->features[0].exts[0].insubstmt_index, 0);
1338 assert_int_equal(mod->parsed->features[0].exts[0].insubstmt, LYEXT_SUBSTMT_SELF);*/
1339
1340 /* min subelems */
1341 TEST_SCHEMA_OK(0, 1, "featuretwo-yin", "<feature name=\"feature-name\"/>", mod)
1342 assert_int_equal(1, LY_ARRAY_COUNT(mod->parsed->features));
1343 assert_string_equal(mod->parsed->features[0].name, "feature-name");
1344
1345 /* invalid substatement */
1346 TEST_SCHEMA_PARSE_ERR(0, 1, "inv", "<feature name=\"feature-name\"><organization><text>org</text></organization></feature>",
1347 "Unexpected sub-element \"organization\" of \"feature\" element.", "Line number 1.");
1348
1349 /*
1350 * compiling
1351 */
1352
1353 TEST_SCHEMA_OK(1, 0, "a", "feature f1 {description test1;reference test2;status current;} feature f2; feature f3;\n"
1354 "feature orfeature {if-feature \"f1 or f2\";}\n"
1355 "feature andfeature {if-feature \"f1 and f2\";}\n"
1356 "feature f6 {if-feature \"not f1\";}\n"
1357 "feature f7 {if-feature \"(f2 and f3) or (not f1)\";}\n"
1358 "feature f8 {if-feature \"f1 or f2 or f3 or orfeature or andfeature\";}\n"
1359 "feature f9 {if-feature \"not not f1\";}", mod);
1360 assert_non_null(mod->parsed->features);
1361 assert_int_equal(9, LY_ARRAY_COUNT(mod->parsed->features));
1362
1363 /* all features are disabled by default */
1364 LY_ARRAY_FOR(mod->parsed->features, struct lysp_feature, f) {
1365 assert_false(f->flags & LYS_FENABLED);
1366 }
1367
1368 /* some invalid expressions */
1369 TEST_SCHEMA_PARSE_ERR(1, 0, "inv", "feature f{if-feature f1;}",
1370 "Invalid value \"f1\" of if-feature - unable to find feature \"f1\".", NULL);
1371 TEST_SCHEMA_PARSE_ERR(1, 0, "inv", "feature f1; feature f2{if-feature 'f and';}",
1372 "Invalid value \"f and\" of if-feature - unexpected end of expression.", NULL);
1373 TEST_SCHEMA_PARSE_ERR(1, 0, "inv", "feature f{if-feature 'or';}",
1374 "Invalid value \"or\" of if-feature - unexpected end of expression.", NULL);
1375 TEST_SCHEMA_PARSE_ERR(1, 0, "inv", "feature f1; feature f2{if-feature '(f1';}",
1376 "Invalid value \"(f1\" of if-feature - non-matching opening and closing parentheses.", NULL);
1377 TEST_SCHEMA_PARSE_ERR(1, 0, "inv", "feature f1; feature f2{if-feature 'f1)';}",
1378 "Invalid value \"f1)\" of if-feature - non-matching opening and closing parentheses.", NULL);
1379 TEST_SCHEMA_PARSE_ERR(1, 0, "inv", "feature f1; feature f2{if-feature ---;}",
1380 "Invalid value \"---\" of if-feature - unable to find feature \"---\".", NULL);
1381 TEST_SCHEMA_PARSE_ERR(0, 0, "inv", "feature f1; feature f2{if-feature 'not f1';}",
1382 "Invalid value \"not f1\" of if-feature - YANG 1.1 expression in YANG 1.0 module.", NULL);
1383
1384 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, "submodule inv_sub {belongs-to inv {prefix inv;} feature f1;}");
1385 TEST_SCHEMA_PARSE_ERR(0, 0, "inv", "feature f1 {if-feature f2;} feature f2 {if-feature f1;}",
1386 "Feature \"f1\" is indirectly referenced from itself.", NULL);
1387 TEST_SCHEMA_PARSE_ERR(0, 0, "inv", "feature f1 {if-feature f1;}",
1388 "Feature \"f1\" is referenced from itself.", NULL);
1389 TEST_SCHEMA_PARSE_ERR(1, 0, "inv", "feature f {if-feature ();}",
1390 "Invalid value \"()\" of if-feature - number of features in expression does not match the required number of operands for the operations.", NULL);
1391 TEST_SCHEMA_PARSE_ERR(1, 0, "inv", "feature f1; feature f {if-feature 'f1(';}",
1392 "Invalid value \"f1(\" of if-feature - non-matching opening and closing parentheses.", NULL);
1393 TEST_SCHEMA_PARSE_ERR(1, 0, "inv", "feature f1; feature f {if-feature 'and f1';}",
1394 "Invalid value \"and f1\" of if-feature - missing feature/expression before \"and\" operation.", NULL);
1395 TEST_SCHEMA_PARSE_ERR(1, 0, "inv", "feature f1; feature f {if-feature 'f1 not ';}",
1396 "Invalid value \"f1 not \" of if-feature - unexpected end of expression.", NULL);
1397 TEST_SCHEMA_PARSE_ERR(1, 0, "inv", "feature f1; feature f {if-feature 'f1 not not ';}",
1398 "Invalid value \"f1 not not \" of if-feature - unexpected end of expression.", NULL);
1399 TEST_SCHEMA_PARSE_ERR(1, 0, "inv", "feature f1; feature f2; feature f {if-feature 'or f1 f2';}",
1400 "Invalid value \"or f1 f2\" of if-feature - missing feature/expression before \"or\" operation.", NULL);
1401
1402 /*
1403 * printing
1404 */
1405
1406 /*
1407 * cleanup
1408 */
1409}
1410
1411static void
1412test_extension_argument(void **state)
1413{
1414 struct lys_module *mod;
1415 const char *mod_def_yang = "module a {\n"
1416 " namespace \"urn:a\";\n"
1417 " prefix a;\n\n"
1418 " extension e {\n"
1419 " argument name;\n"
1420 " }\n\n"
1421 " a:e \"aaa\";\n"
1422 "}\n";
1423 const char *mod_def_yin =
1424 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1425 "<module name=\"a\"\n"
1426 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
1427 " xmlns:a=\"urn:a\">\n"
1428 " <namespace uri=\"urn:a\"/>\n"
1429 " <prefix value=\"a\"/>\n"
1430 " <extension name=\"e\">\n"
1431 " <argument name=\"name\"/>\n"
1432 " </extension>\n"
1433 " <a:e name=\"aaa\"/>\n"
1434 "</module>\n";
1435 const char *mod_test_yin, *mod_test_yang;
1436 char *printed;
1437
1438 mod_test_yang = "module b {\n"
1439 " namespace \"urn:b\";\n"
1440 " prefix b;\n\n"
1441 " import a {\n"
1442 " prefix a;\n"
1443 " }\n\n"
1444 " a:e \"xxx\";\n"
1445 "}\n";
1446 mod_test_yin =
1447 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1448 "<module name=\"b\"\n"
1449 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
1450 " xmlns:b=\"urn:b\"\n"
1451 " xmlns:a=\"urn:a\">\n"
1452 " <namespace uri=\"urn:b\"/>\n"
1453 " <prefix value=\"b\"/>\n"
1454 " <import module=\"a\">\n"
1455 " <prefix value=\"a\"/>\n"
1456 " </import>\n"
1457 " <a:e name=\"xxx\"/>\n"
1458 "</module>\n";
1459
1460 /* from YANG */
1461 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_def_yang);
1462 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, mod_test_yang, LYS_IN_YANG, &mod));
1463 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
1464 assert_string_equal(printed, mod_test_yang);
1465 free(printed);
1466
1467 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
1468 assert_string_equal(printed, mod_test_yin);
1469 free(printed);
1470
1471 assert_non_null(mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL));
1472 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
1473 assert_string_equal(printed, mod_def_yang);
1474 free(printed);
1475
1476 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
1477 assert_string_equal(printed, mod_def_yin);
1478 free(printed);
1479
1480 /* context reset */
1481 ly_ctx_destroy(UTEST_LYCTX);
1482 ly_ctx_new(NULL, 0, &UTEST_LYCTX);
1483
1484 /* from YIN */
1485 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_def_yin);
1486 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, &mod));
1487 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
1488 assert_string_equal(printed, mod_test_yang);
1489 free(printed);
1490
1491 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
1492 assert_string_equal(printed, mod_test_yin);
1493 free(printed);
1494
1495 assert_non_null(mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL));
1496 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
1497 assert_string_equal(printed, mod_def_yang);
1498 free(printed);
1499
1500 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
1501 assert_string_equal(printed, mod_def_yin);
1502 free(printed);
1503}
1504
1505static void
1506test_extension_argument_element(void **state)
1507{
1508 struct lys_module *mod;
1509 const char *mod_def_yang = "module a {\n"
1510 " namespace \"urn:a\";\n"
1511 " prefix a;\n\n"
1512 " extension e {\n"
1513 " argument name {\n"
1514 " yin-element true;\n"
1515 " }\n"
1516 " }\n\n"
1517 " a:e \"aaa\";\n"
1518 "}\n";
1519 const char *mod_def_yin =
1520 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1521 "<module name=\"a\"\n"
1522 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
1523 " xmlns:a=\"urn:a\">\n"
1524 " <namespace uri=\"urn:a\"/>\n"
1525 " <prefix value=\"a\"/>\n"
1526 " <extension name=\"e\">\n"
1527 " <argument name=\"name\">\n"
1528 " <yin-element value=\"true\"/>\n"
1529 " </argument>\n"
1530 " </extension>\n"
1531 " <a:e>\n"
1532 " <a:name>aaa</a:name>\n"
1533 " </a:e>\n"
1534 "</module>\n";
1535 const char *mod_test_yin, *mod_test_yang;
1536 char *printed;
1537
1538 mod_test_yang = "module b {\n"
1539 " namespace \"urn:b\";\n"
1540 " prefix b;\n\n"
1541 " import a {\n"
1542 " prefix a;\n"
1543 " }\n\n"
1544 " a:e \"xxx\";\n"
1545 "}\n";
1546 mod_test_yin =
1547 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1548 "<module name=\"b\"\n"
1549 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
1550 " xmlns:b=\"urn:b\"\n"
1551 " xmlns:a=\"urn:a\">\n"
1552 " <namespace uri=\"urn:b\"/>\n"
1553 " <prefix value=\"b\"/>\n"
1554 " <import module=\"a\">\n"
1555 " <prefix value=\"a\"/>\n"
1556 " </import>\n"
1557 " <a:e>\n"
1558 " <a:name>xxx</a:name>\n"
1559 " </a:e>\n"
1560 "</module>\n";
1561
1562 /* from YANG */
1563 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_def_yang);
1564 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, mod_test_yang, LYS_IN_YANG, &mod));
1565 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
1566 assert_string_equal(printed, mod_test_yang);
1567 free(printed);
1568
1569 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
1570 assert_string_equal(printed, mod_test_yin);
1571 free(printed);
1572
1573 assert_non_null(mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL));
1574 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
1575 assert_string_equal(printed, mod_def_yang);
1576 free(printed);
1577
1578 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
1579 assert_string_equal(printed, mod_def_yin);
1580 free(printed);
1581
1582 /* context reset */
1583 ly_ctx_destroy(UTEST_LYCTX);
1584 ly_ctx_new(NULL, 0, &UTEST_LYCTX);
1585
1586 /* from YIN */
1587 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_def_yin);
1588 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, &mod));
1589 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
1590 assert_string_equal(printed, mod_test_yang);
1591 free(printed);
1592
1593 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
1594 assert_string_equal(printed, mod_test_yin);
1595 free(printed);
1596
1597 assert_non_null(mod = ly_ctx_get_module(UTEST_LYCTX, "a", NULL));
1598 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0));
1599 assert_string_equal(printed, mod_def_yang);
1600 free(printed);
1601
1602 assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0));
1603 assert_string_equal(printed, mod_def_yin);
1604 free(printed);
1605
1606 /* invalid */
1607 mod_test_yang = "module x { namespace \"urn:x\"; prefix x; import a { prefix a; } a:e; }";
1608 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yang, LYS_IN_YANG, NULL));
1609 CHECK_LOG_CTX("Extension instance \"a:e\" misses argument element \"name\".", "/x:{extension='a:e'}");
1610
1611 mod_test_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1612 "<module name=\"x\"\n"
1613 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
1614 " xmlns:x=\"urn:x\"\n"
1615 " xmlns:a=\"urn:a\">\n"
1616 " <namespace uri=\"urn:x\"/>\n"
1617 " <prefix value=\"x\"/>\n"
1618 " <import module=\"a\">\n"
1619 " <prefix value=\"a\"/>\n"
1620 " </import>\n\n"
1621 " <a:e/>\n"
1622 "</module>\n";
1623 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, NULL));
1624 CHECK_LOG_CTX("Extension instance \"a:e\" misses argument element \"name\".", "/x:{extension='a:e'}");
1625
1626 mod_test_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1627 "<module name=\"x\"\n"
1628 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
1629 " xmlns:x=\"urn:x\"\n"
1630 " xmlns:a=\"urn:a\">\n"
1631 " <namespace uri=\"urn:x\"/>\n"
1632 " <prefix value=\"x\"/>\n"
1633 " <import module=\"a\">\n"
1634 " <prefix value=\"a\"/>\n"
1635 " </import>\n\n"
1636 " <a:e name=\"xxx\"/>\n"
1637 "</module>\n";
1638 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, NULL));
1639 CHECK_LOG_CTX("Extension instance \"a:e\" misses argument element \"name\".", "/x:{extension='a:e'}");
1640
1641 mod_test_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1642 "<module name=\"x\"\n"
1643 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
1644 " xmlns:x=\"urn:x\"\n"
1645 " xmlns:a=\"urn:a\">\n"
1646 " <namespace uri=\"urn:x\"/>\n"
1647 " <prefix value=\"x\"/>\n"
1648 " <import module=\"a\">\n"
1649 " <prefix value=\"a\"/>\n"
1650 " </import>\n\n"
1651 " <a:e>\n"
1652 " <x:name>xxx</x:name>\n"
1653 " </a:e>\n"
1654 "</module>\n";
1655 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, NULL));
1656 CHECK_LOG_CTX("Extension instance \"a:e\" element and its argument element \"name\" are expected in the same namespace, but they differ.",
1657 "/x:{extension='a:e'}");
1658
1659 mod_test_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1660 "<module name=\"x\"\n"
1661 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
1662 " xmlns:x=\"urn:x\"\n"
1663 " xmlns:a=\"urn:a\">\n"
1664 " <namespace uri=\"urn:x\"/>\n"
1665 " <prefix value=\"x\"/>\n"
1666 " <import module=\"a\">\n"
1667 " <prefix value=\"a\"/>\n"
1668 " </import>\n\n"
1669 " <a:e>\n"
1670 " <a:value>xxx</a:value>\n"
1671 " </a:e>\n"
1672 "</module>\n";
1673 assert_int_equal(LY_EVALID, lys_parse_mem(UTEST_LYCTX, mod_test_yin, LYS_IN_YIN, NULL));
1674 CHECK_LOG_CTX("Extension instance \"a:e\" expects argument element \"name\" as its first XML child, but \"value\" element found.",
1675 "/x:{extension='a:e'}");
1676
1677}
1678
1679static void
1680test_extension_compile(void **state)
1681{
1682 struct lys_module *mod;
1683 struct lysc_ctx cctx = {0};
1684 struct lysp_ext_instance ext_p = {0};
1685 struct lysp_stmt child = {0};
1686 struct lysc_ext_instance ext_c = {0};
1687 struct lysc_ext_substmt *substmt;
1688 LY_ERR rc = LY_SUCCESS;
1689
1690 /* current module, whatever */
1691 mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "yang");
1692 assert_true(mod);
1693
1694 /* compile context */
1695 cctx.ctx = UTEST_LYCTX;
1696 cctx.cur_mod = mod;
1697 cctx.pmod = mod->parsed;
1698 cctx.path_len = 1;
1699 cctx.path[0] = '/';
1700
1701 /* parsed ext instance */
1702 lydict_insert(UTEST_LYCTX, "pref:my-ext", 0, &ext_p.name);
1703 ext_p.format = LY_VALUE_JSON;
1704 ext_p.parent_stmt = LY_STMT_MODULE;
1705
1706 /* compiled ext instance */
1707 ext_c.parent_stmt = ext_p.parent_stmt;
1708 // ext_c.parent =
1709 LY_ARRAY_NEW_GOTO(UTEST_LYCTX, ext_c.substmts, substmt, rc, cleanup);
1710
1711 /*
1712 * error-message
1713 */
1714 ext_p.child = &child;
1715 lydict_insert(UTEST_LYCTX, "error-message", 0, &child.stmt);
1716 lydict_insert(UTEST_LYCTX, "my error", 0, &child.arg);
1717 child.format = LY_VALUE_JSON;
1718 child.kw = LY_STMT_ERROR_MESSAGE;
1719
1720 substmt->stmt = LY_STMT_ERROR_MESSAGE;
1721 substmt->cardinality = LY_STMT_CARD_OPT;
1722 substmt->storage = &ext_c.data;
1723
1724 /* compile */
1725 assert_int_equal(LY_SUCCESS, lys_compile_extension_instance(&cctx, &ext_p, &ext_c));
1726
1727 /* check */
1728 assert_string_equal(ext_c.data, "my error");
1729
1730cleanup:
1731 lydict_remove(UTEST_LYCTX, ext_p.name);
1732 lydict_remove(UTEST_LYCTX, child.stmt);
1733 lydict_remove(UTEST_LYCTX, child.arg);
1734 LY_ARRAY_FREE(ext_c.substmts);
1735
1736 lydict_remove(UTEST_LYCTX, ext_c.data);
1737 if (rc) {
1738 fail();
1739 }
1740}
1741
1742static void
1743test_ext_recursive(void **state)
1744{
1745 const char *mod_base_yang, *mod_imp_yang, *mod_base_yin, *mod_imp_yin;
1746
1747 mod_imp_yang = "module b {\n"
1748 " namespace \"urn:b\";\n"
1749 " prefix b;\n\n"
1750 " extension use-in {\n"
1751 " argument name {\n"
1752 " b:arg-type {\n"
1753 " type string;\n"
1754 " }\n"
1755 " }\n"
1756 " b:use-in \"extension\";\n"
1757 " b:occurence \"*\";\n"
1758 " }\n"
1759 "\n"
1760 " extension substatement {\n"
1761 " argument name {\n"
1762 " b:arg-type {\n"
1763 " type string;\n"
1764 " }\n"
1765 " }\n"
1766 " b:use-in \"extension\";\n"
1767 " b:occurence \"*\";\n"
1768 " b:substatement \"b:occurence\";\n"
1769 " }\n"
1770 "\n"
1771 " extension arg-type {\n"
1772 " b:use-in \"argument\";\n"
1773 " b:substatement \"type\" {\n"
1774 " b:occurence \"1\";\n"
1775 " }\n"
1776 " b:substatement \"default\";\n"
1777 " }\n"
1778 "\n"
1779 " extension occurence {\n"
1780 " argument value {\n"
1781 " b:arg-type {\n"
1782 " type enumeration {\n"
1783 " enum \"?\";\n"
1784 " enum \"*\";\n"
1785 " enum \"+\";\n"
1786 " enum \"1\";\n"
1787 " }\n"
1788 " }\n"
1789 " }\n"
1790 " b:use-in \"extension\";\n"
1791 " }\n"
1792 "}\n";
1793
1794 mod_imp_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1795 "<module name=\"b\"\n"
1796 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
1797 " xmlns:b=\"urn:b\"\n"
1798 " xmlns:a=\"urn:a\">\n"
1799 " <namespace uri=\"urn:b\"/>\n"
1800 " <prefix value=\"b\"/>\n"
1801 " <import module=\"a\">\n"
1802 " <prefix value=\"a\"/>\n"
1803 " </import>\n\n"
1804 " <a:e name=\"xxx\"/>\n"
1805 "</module>\n";
1806
1807 mod_base_yang = "module a {\n"
1808 " namespace \"urn:a\";\n"
1809 " prefix a;\n\n"
1810 " import b {\n"
1811 " prefix b;\n"
1812 " }\n"
1813 "\n"
1814 " extension abstract {\n"
1815 " b:use-in \"identity\";\n"
1816 " }\n"
1817 "\n"
1818 " identity mount-id;\n"
1819 "\n"
1820 " identity yang-lib-id {\n"
1821 " base mount-id;\n"
1822 " a:abstract;\n"
1823 " }\n"
1824 "}\n";
1825
1826 mod_base_yin = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1827 "<module name=\"a\"\n"
1828 " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n"
1829 " xmlns:a=\"urn:a\">\n"
1830 " <namespace uri=\"urn:a\"/>\n"
1831 " <prefix value=\"a\"/>\n\n"
1832 " <extension name=\"e\">\n"
1833 " <argument name=\"name\"/>\n"
1834 " </extension>\n\n"
1835 " <a:e name=\"aaa\"/>\n"
1836 "</module>\n";
1837
1838 /* from YANG */
1839 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_imp_yang);
1840 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, mod_base_yang, LYS_IN_YANG, NULL));
1841
1842 /* context reset */
1843 ly_ctx_destroy(UTEST_LYCTX);
1844 ly_ctx_new(NULL, 0, &UTEST_LYCTX);
1845
1846 /* from YIN */
1847 ly_ctx_set_module_imp_clb(UTEST_LYCTX, test_imp_clb, (void *)mod_imp_yin);
1848 assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, mod_base_yin, LYS_IN_YIN, NULL));
1849}
Radek Krejci85ac8312021-03-03 20:21:33 +01001850
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001851int
1852main(void)
Radek Krejci3a4889a2020-05-19 17:01:58 +02001853{
1854 const struct CMUnitTest tests[] = {
Radek Iša56ca9e42020-09-08 18:42:00 +02001855 UTEST(test_getnext),
1856 UTEST(test_date),
1857 UTEST(test_revisions),
aPiecek4f49a142021-06-29 15:32:39 +02001858 UTEST(test_collision_typedef),
aPiecek0b365612021-06-30 13:12:58 +02001859 UTEST(test_collision_grouping),
aPiecek14d07f02021-06-30 09:46:50 +02001860 UTEST(test_collision_identity),
1861 UTEST(test_collision_feature),
Radek Iša56ca9e42020-09-08 18:42:00 +02001862 UTEST(test_accessible_tree),
Radek Krejci589c5472021-01-20 10:29:06 +01001863 UTEST(test_includes),
Michal Vaskoac4450e2021-11-09 13:53:40 +01001864 UTEST(test_key_order),
Michal Vaskof4fa90d2021-11-11 15:05:19 +01001865 UTEST(test_disabled_enum),
Radek Iša56ca9e42020-09-08 18:42:00 +02001866 UTEST(test_identity),
1867 UTEST(test_feature),
Radek Krejci85ac8312021-03-03 20:21:33 +01001868 UTEST(test_extension_argument),
1869 UTEST(test_extension_argument_element),
Michal Vasko633ae8a2022-08-25 09:52:02 +02001870 UTEST(test_extension_compile),
Michal Vasko002d4032022-08-03 12:13:32 +02001871 UTEST(test_ext_recursive),
Radek Krejci3a4889a2020-05-19 17:01:58 +02001872 };
1873
1874 return cmocka_run_group_tests(tests, NULL, NULL);
1875}