blob: d0dcae5994d8719716a4da7db248c7167b2ea09b [file] [log] [blame]
Michal Vaskob1b5c262020-03-05 14:29:47 +01001/**
2 * @file test_validation.c
Michal Vaskocde73ac2019-11-14 16:10:27 +01003 * @author: Radek Krejci <rkrejci@cesnet.cz>
Michal Vaskob1b5c262020-03-05 14:29:47 +01004 * @brief unit tests for functions from validation.c
Michal Vaskocde73ac2019-11-14 16:10:27 +01005 *
Michal Vaskob1b5c262020-03-05 14:29:47 +01006 * Copyright (c) 2020 CESNET, z.s.p.o.
Michal Vaskocde73ac2019-11-14 16:10:27 +01007 *
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 */
Radek Iša56ca9e42020-09-08 18:42:00 +020014#define _UTEST_MAIN_
15#include "utests.h"
Michal Vaskocde73ac2019-11-14 16:10:27 +010016
Michal Vaskocde73ac2019-11-14 16:10:27 +010017#include <stdio.h>
18#include <string.h>
19
Radek Krejci70593c12020-06-13 20:48:09 +020020#include "context.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020021#include "in.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020022#include "out.h"
Radek Krejcib4ac5a92020-11-23 17:54:33 +010023#include "parser_data.h"
Radek Krejci70593c12020-06-13 20:48:09 +020024#include "printer_data.h"
Radek Krejcief5f7672021-04-01 17:04:12 +020025#include "tests_config.h"
Radek Krejci70593c12020-06-13 20:48:09 +020026#include "tree_data_internal.h"
Radek Krejcib4ac5a92020-11-23 17:54:33 +010027#include "tree_schema.h"
Michal Vaskocde73ac2019-11-14 16:10:27 +010028
Radek Iša56ca9e42020-09-08 18:42:00 +020029#define LYD_TREE_CREATE(INPUT, MODEL) \
30 CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, MODEL)
Michal Vaskocde73ac2019-11-14 16:10:27 +010031
Michal Vaskocde73ac2019-11-14 16:10:27 +010032static void
Radek Iša56ca9e42020-09-08 18:42:00 +020033test_when(void **state)
Michal Vaskocde73ac2019-11-14 16:10:27 +010034{
Radek Iša56ca9e42020-09-08 18:42:00 +020035 struct lyd_node *tree;
36 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +010037 "module a {\n"
38 " namespace urn:tests:a;\n"
39 " prefix a;\n"
40 " yang-version 1.1;\n"
41 "\n"
42 " container cont {\n"
43 " leaf a {\n"
44 " when \"../../c = 'val_c'\";\n"
45 " type string;\n"
46 " }\n"
47 " leaf b {\n"
48 " type string;\n"
49 " }\n"
50 " }\n"
51 " leaf c {\n"
52 " when \"/cont/b = 'val_b'\";\n"
53 " type string;\n"
54 " }\n"
55 "}";
Radek Iša56ca9e42020-09-08 18:42:00 +020056
57 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
58
59 CHECK_PARSE_LYD_PARAM("<c xmlns=\"urn:tests:a\">hey</c>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +020060 CHECK_LOG_CTX("When condition \"/cont/b = 'val_b'\" not satisfied.", "Data location \"/a:c\".");
Radek Iša56ca9e42020-09-08 18:42:00 +020061
62 LYD_TREE_CREATE("<cont xmlns=\"urn:tests:a\"><b>val_b</b></cont><c xmlns=\"urn:tests:a\">hey</c>", tree);
63 CHECK_LYSC_NODE(tree->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "c", 0, LYS_LEAF, 0, 0, NULL, 1);
64 assert_int_equal(LYD_WHEN_TRUE, tree->next->flags);
65 lyd_free_all(tree);
66
67 LYD_TREE_CREATE("<cont xmlns=\"urn:tests:a\"><a>val</a><b>val_b</b></cont><c xmlns=\"urn:tests:a\">val_c</c>", tree);
68 CHECK_LYSC_NODE(lyd_child(tree)->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "a", 1, LYS_LEAF, 1, 0, NULL, 1);
69 assert_int_equal(LYD_WHEN_TRUE, lyd_child(tree)->flags);
70 CHECK_LYSC_NODE(tree->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "c", 0, LYS_LEAF, 0, 0, NULL, 1);
71 assert_int_equal(LYD_WHEN_TRUE, tree->next->flags);
72 lyd_free_all(tree);
73}
74
75static void
Christian Hoppsb6ecaea2021-02-06 09:45:38 -050076test_mandatory_when(void **state)
77{
78 struct lyd_node *tree;
79 const char *schema =
80 "module a {\n"
81 " namespace urn:tests:a;\n"
82 " prefix a;\n"
83 " yang-version 1.1;\n"
84 "\n"
85 " container cont {\n"
86 " leaf a {\n"
87 " type string;\n"
88 " }\n"
89 " leaf b {\n"
90 " when \"../a = 'val_a'\";\n"
91 " mandatory true;\n"
92 " type string;\n"
93 " }\n"
94 " }\n"
95 " leaf c {\n"
96 " type string;\n"
97 " }\n"
98 " leaf d {\n"
99 " when \"../c = 'val_c'\";\n"
100 " mandatory true;\n"
101 " type string;\n"
102 " }\n"
103 "}";
104
105 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
106
107 CHECK_PARSE_LYD_PARAM("<d xmlns=\"urn:tests:a\">hey</d>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +0200108 CHECK_LOG_CTX("When condition \"../c = 'val_c'\" not satisfied.", "Data location \"/a:d\".");
Christian Hoppsb6ecaea2021-02-06 09:45:38 -0500109
110 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:a\"><b>hey</b></cont>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +0200111 CHECK_LOG_CTX("When condition \"../a = 'val_a'\" not satisfied.", "Data location \"/a:cont/b\".");
Christian Hoppsb6ecaea2021-02-06 09:45:38 -0500112
113 LYD_TREE_CREATE("<c xmlns=\"urn:tests:a\">val_c</c><d xmlns=\"urn:tests:a\">hey</d>", tree);
114 CHECK_LYSC_NODE(tree->next->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_MAND_TRUE, 1, "d", 0, LYS_LEAF, 0, 0, NULL, 1);
115 assert_int_equal(LYD_WHEN_TRUE, tree->next->next->flags);
116 lyd_free_all(tree);
117
118 LYD_TREE_CREATE("<cont xmlns=\"urn:tests:a\"><a>val_a</a><b>hey</b></cont>", tree);
119 CHECK_LYSC_NODE(lyd_child(tree)->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_MAND_TRUE, 1, "b", 0, LYS_LEAF, tree->schema, 0, NULL, 1);
120 assert_int_equal(LYD_WHEN_TRUE, lyd_child(tree)->next->flags);
121 lyd_free_all(tree);
122}
123
124static void
Michal Vasko850d8cb2022-08-05 12:51:00 +0200125test_type_incomplete_when(void **state)
126{
127 struct lys_module *mod;
128 struct lyd_node *tree;
129 const char *schema =
130 "module a {\n"
131 " namespace urn:tests:a;\n"
132 " prefix a;\n"
133 " yang-version 1.1;\n"
134 "\n"
135 " container cont {\n"
136 " when \"../c = 'val_c'\";\n"
137 " leaf a {\n"
138 " type leafref {\n"
139 " path \"/a:c\";\n"
140 " }\n"
141 " }\n"
142 " leaf b {\n"
143 " type string;\n"
144 " }\n"
145 " }\n"
146 " leaf c {\n"
147 " type string;\n"
148 " }\n"
149 "}";
150
151 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
152
153 LYD_TREE_CREATE("<cont xmlns=\"urn:tests:a\"><a>val_c</a><b>val</b></cont><c xmlns=\"urn:tests:a\">val_c</c>", tree);
154
155 /* make the when false */
156 assert_int_equal(LY_SUCCESS, lyd_change_term(tree->next, "wrong-val"));
157
158 /* autodelete when with a leafref */
159 assert_int_equal(LY_SUCCESS, lyd_validate_module(&tree, mod, 0, NULL));
160 assert_string_equal(LYD_NAME(tree), "c");
161 assert_null(tree->next);
162
163 lyd_free_all(tree);
164}
165
166static void
Radek Iša56ca9e42020-09-08 18:42:00 +0200167test_mandatory(void **state)
168{
169 struct lyd_node *tree;
170 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100171 "module b {\n"
172 " namespace urn:tests:b;\n"
173 " prefix b;\n"
174 " yang-version 1.1;\n"
175 "\n"
176 " choice choic {\n"
177 " mandatory true;\n"
178 " leaf a {\n"
179 " type string;\n"
180 " }\n"
181 " case b {\n"
182 " leaf l {\n"
183 " type string;\n"
184 " }\n"
185 " }\n"
186 " }\n"
187 " leaf c {\n"
188 " mandatory true;\n"
189 " type string;\n"
190 " }\n"
191 " leaf d {\n"
192 " type empty;\n"
193 " }\n"
194 "}";
Radek Iša56ca9e42020-09-08 18:42:00 +0200195
196 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
197
198 CHECK_PARSE_LYD_PARAM("<d xmlns=\"urn:tests:b\"/>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vasko959f8d82022-06-16 07:51:50 +0200199 CHECK_LOG_CTX_APPTAG("Mandatory choice \"choic\" data do not exist.", "Schema location \"/b:choic\".", "missing-choice");
Radek Iša56ca9e42020-09-08 18:42:00 +0200200
201 CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:b\">string</l><d xmlns=\"urn:tests:b\"/>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vasko959f8d82022-06-16 07:51:50 +0200202 CHECK_LOG_CTX("Mandatory node \"c\" instance does not exist.", "Schema location \"/b:c\".");
Radek Iša56ca9e42020-09-08 18:42:00 +0200203
204 CHECK_PARSE_LYD_PARAM("<a xmlns=\"urn:tests:b\">string</a>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vasko959f8d82022-06-16 07:51:50 +0200205 CHECK_LOG_CTX("Mandatory node \"c\" instance does not exist.", "Schema location \"/b:c\".");
Radek Iša56ca9e42020-09-08 18:42:00 +0200206
207 LYD_TREE_CREATE("<a xmlns=\"urn:tests:b\">string</a><c xmlns=\"urn:tests:b\">string2</c>", tree);
208 lyd_free_siblings(tree);
209}
210
211static void
212test_minmax(void **state)
213{
214 struct lyd_node *tree;
215 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100216 "module c {\n"
217 " namespace urn:tests:c;\n"
218 " prefix c;\n"
219 " yang-version 1.1;\n"
220 "\n"
221 " choice choic {\n"
222 " leaf a {\n"
223 " type string;\n"
224 " }\n"
225 " case b {\n"
226 " leaf-list l {\n"
227 " min-elements 3;\n"
228 " type string;\n"
229 " }\n"
230 " }\n"
231 " }\n"
232 " list lt {\n"
233 " max-elements 4;\n"
234 " key \"k\";\n"
235 " leaf k {\n"
236 " type string;\n"
237 " }\n"
238 " }\n"
239 " leaf d {\n"
240 " type empty;\n"
241 " }\n"
242 "}";
Radek Iša56ca9e42020-09-08 18:42:00 +0200243
244 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
245
Michal Vasko6c16cda2021-02-04 11:05:52 +0100246 CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:c\">mate</l>"
247 "<d xmlns=\"urn:tests:c\"/>",
248 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vasko959f8d82022-06-16 07:51:50 +0200249 CHECK_LOG_CTX_APPTAG("Too few \"l\" instances.", "Schema location \"/c:choic/b/l\".", "too-few-elements");
Radek Iša56ca9e42020-09-08 18:42:00 +0200250
251 CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:c\">val1</l>"
252 "<l xmlns=\"urn:tests:c\">val2</l>",
253 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vasko959f8d82022-06-16 07:51:50 +0200254 CHECK_LOG_CTX_APPTAG("Too few \"l\" instances.", "Schema location \"/c:choic/b/l\".", "too-few-elements");
Radek Iša56ca9e42020-09-08 18:42:00 +0200255
256 LYD_TREE_CREATE("<l xmlns=\"urn:tests:c\">val1</l>"
257 "<l xmlns=\"urn:tests:c\">val2</l>"
258 "<l xmlns=\"urn:tests:c\">val3</l>", tree);
259 lyd_free_all(tree);
260
261 CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:c\">val1</l>"
262 "<l xmlns=\"urn:tests:c\">val2</l>"
263 "<l xmlns=\"urn:tests:c\">val3</l>"
264 "<lt xmlns=\"urn:tests:c\"><k>val1</k></lt>"
265 "<lt xmlns=\"urn:tests:c\"><k>val2</k></lt>"
266 "<lt xmlns=\"urn:tests:c\"><k>val3</k></lt>"
267 "<lt xmlns=\"urn:tests:c\"><k>val4</k></lt>"
Radek Krejci2efc45b2020-12-22 16:25:44 +0100268 "<lt xmlns=\"urn:tests:c\"><k>val5</k></lt>"
269 "<lt xmlns=\"urn:tests:c\"><k>val6</k></lt>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +0200270 CHECK_LOG_CTX_APPTAG("Too many \"lt\" instances.", "Data location \"/c:lt[k='val5']\".",
Michal Vaskoe9391c72021-10-05 10:04:56 +0200271 "too-many-elements");
Radek Iša56ca9e42020-09-08 18:42:00 +0200272}
273
274const char *schema_d =
275 "module d {\n"
276 " namespace urn:tests:d;\n"
277 " prefix d;\n"
278 " yang-version 1.1;\n"
279 "\n"
280 " list lt {\n"
281 " key \"k\";\n"
282 " unique \"l1\";\n"
283 " leaf k {\n"
284 " type string;\n"
285 " }\n"
286 " leaf l1 {\n"
287 " type string;\n"
288 " }\n"
289 " }\n"
290 " list lt2 {\n"
291 " key \"k\";\n"
292 " unique \"cont/l2 l4\";\n"
293 " unique \"l5 l6\";\n"
294 " leaf k {\n"
295 " type string;\n"
296 " }\n"
297 " container cont {\n"
298 " leaf l2 {\n"
299 " type string;\n"
300 " }\n"
301 " }\n"
302 " leaf l4 {\n"
303 " type string;\n"
304 " }\n"
305 " leaf l5 {\n"
306 " type string;\n"
307 " }\n"
308 " leaf l6 {\n"
309 " type string;\n"
310 " }\n"
311 " list lt3 {\n"
312 " key \"kk\";\n"
313 " unique \"l3\";\n"
314 " leaf kk {\n"
315 " type string;\n"
316 " }\n"
317 " leaf l3 {\n"
318 " type string;\n"
319 " }\n"
320 " }\n"
321 " }\n"
322 "}";
323
324static void
325test_unique(void **state)
326{
327 struct lyd_node *tree;
328
329 UTEST_ADD_MODULE(schema_d, LYS_IN_YANG, NULL, NULL);
330
331 LYD_TREE_CREATE("<lt xmlns=\"urn:tests:d\">\n"
332 " <k>val1</k>\n"
333 " <l1>same</l1>\n"
334 "</lt>\n"
335 "<lt xmlns=\"urn:tests:d\">\n"
336 " <k>val2</k>\n"
337 "</lt>", tree);
338 lyd_free_all(tree);
339
340 LYD_TREE_CREATE("<lt xmlns=\"urn:tests:d\">\n"
341 " <k>val1</k>\n"
342 " <l1>same</l1>\n"
343 "</lt>\n"
344 "<lt xmlns=\"urn:tests:d\">\n"
345 " <k>val2</k>\n"
346 " <l1>not-same</l1>\n"
347 "</lt>", tree);
348 lyd_free_all(tree);
349
350 CHECK_PARSE_LYD_PARAM("<lt xmlns=\"urn:tests:d\">\n"
351 " <k>val1</k>\n"
352 " <l1>same</l1>\n"
353 "</lt>\n"
354 "<lt xmlns=\"urn:tests:d\">\n"
355 " <k>val2</k>\n"
356 " <l1>same</l1>\n"
357 "</lt>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskoe9391c72021-10-05 10:04:56 +0200358 CHECK_LOG_CTX_APPTAG("Unique data leaf(s) \"l1\" not satisfied in \"/d:lt[k='val1']\" and \"/d:lt[k='val2']\".",
Michal Vaskodbf3e652022-10-21 08:46:25 +0200359 "Data location \"/d:lt[k='val2']\".", "data-not-unique");
Radek Iša56ca9e42020-09-08 18:42:00 +0200360
361 /* now try with more instances */
362 LYD_TREE_CREATE("<lt xmlns=\"urn:tests:d\">\n"
363 " <k>val1</k>\n"
364 " <l1>1</l1>\n"
365 "</lt>\n"
366 "<lt xmlns=\"urn:tests:d\">\n"
367 " <k>val2</k>\n"
368 " <l1>2</l1>\n"
369 "</lt>\n"
370 "<lt xmlns=\"urn:tests:d\">\n"
371 " <k>val3</k>\n"
372 " <l1>3</l1>\n"
373 "</lt>\n"
374 "<lt xmlns=\"urn:tests:d\">\n"
375 " <k>val4</k>\n"
376 " <l1>4</l1>\n"
377 "</lt>\n"
378 "<lt xmlns=\"urn:tests:d\">\n"
379 " <k>val5</k>\n"
380 " <l1>5</l1>\n"
381 "</lt>\n"
382 "<lt xmlns=\"urn:tests:d\">\n"
383 " <k>val6</k>\n"
384 " <l1>6</l1>\n"
385 "</lt>\n"
386 "<lt xmlns=\"urn:tests:d\">\n"
387 " <k>val7</k>\n"
388 " <l1>7</l1>\n"
389 "</lt>\n"
390 "<lt xmlns=\"urn:tests:d\">\n"
391 " <k>val8</k>\n"
392 " <l1>8</l1>\n"
393 "</lt>", tree);
394 lyd_free_all(tree);
395
396 LYD_TREE_CREATE("<lt xmlns=\"urn:tests:d\">\n"
397 " <k>val1</k>\n"
398 " <l1>1</l1>\n"
399 "</lt>\n"
400 "<lt xmlns=\"urn:tests:d\">\n"
401 " <k>val2</k>\n"
402 " <l1>2</l1>\n"
403 "</lt>\n"
404 "<lt xmlns=\"urn:tests:d\">\n"
405 " <k>val3</k>\n"
406 " <l1>3</l1>\n"
407 "</lt>\n"
408 "<lt xmlns=\"urn:tests:d\">\n"
409 " <k>val4</k>\n"
410 "</lt>\n"
411 "<lt xmlns=\"urn:tests:d\">\n"
412 " <k>val5</k>\n"
413 " <l1>5</l1>\n"
414 "</lt>\n"
415 "<lt xmlns=\"urn:tests:d\">\n"
416 " <k>val6</k>\n"
417 " <l1>6</l1>\n"
418 "</lt>\n"
419 "<lt xmlns=\"urn:tests:d\">\n"
420 " <k>val7</k>\n"
421 "</lt>\n"
422 "<lt xmlns=\"urn:tests:d\">\n"
423 " <k>val8</k>\n"
424 "</lt>", tree);
425 lyd_free_all(tree);
426
427 CHECK_PARSE_LYD_PARAM("<lt xmlns=\"urn:tests:d\">\n"
428 " <k>val1</k>\n"
429 " <l1>1</l1>\n"
430 "</lt>\n"
431 "<lt xmlns=\"urn:tests:d\">\n"
432 " <k>val2</k>\n"
433 " <l1>2</l1>\n"
434 "</lt>\n"
435 "<lt xmlns=\"urn:tests:d\">\n"
436 " <k>val3</k>\n"
437 "</lt>\n"
438 "<lt xmlns=\"urn:tests:d\">\n"
439 " <k>val4</k>\n"
440 " <l1>4</l1>\n"
441 "</lt>\n"
442 "<lt xmlns=\"urn:tests:d\">\n"
443 " <k>val5</k>\n"
444 "</lt>\n"
445 "<lt xmlns=\"urn:tests:d\">\n"
446 " <k>val6</k>\n"
447 "</lt>\n"
448 "<lt xmlns=\"urn:tests:d\">\n"
449 " <k>val7</k>\n"
450 " <l1>2</l1>\n"
451 "</lt>\n"
452 "<lt xmlns=\"urn:tests:d\">\n"
453 " <k>val8</k>\n"
454 " <l1>8</l1>\n"
455 "</lt>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskoe9391c72021-10-05 10:04:56 +0200456 CHECK_LOG_CTX_APPTAG("Unique data leaf(s) \"l1\" not satisfied in \"/d:lt[k='val7']\" and \"/d:lt[k='val2']\".",
Michal Vaskodbf3e652022-10-21 08:46:25 +0200457 "Data location \"/d:lt[k='val2']\".", "data-not-unique");
Radek Iša56ca9e42020-09-08 18:42:00 +0200458}
459
460static void
461test_unique_nested(void **state)
462{
463 struct lyd_node *tree;
464
465 UTEST_ADD_MODULE(schema_d, LYS_IN_YANG, NULL, NULL);
466
467 /* nested list uniquest are compared only with instances in the same parent list instance */
468 LYD_TREE_CREATE("<lt2 xmlns=\"urn:tests:d\">\n"
469 " <k>val1</k>\n"
470 " <cont>\n"
471 " <l2>1</l2>\n"
472 " </cont>\n"
473 " <l4>1</l4>\n"
474 "</lt2>\n"
475 "<lt2 xmlns=\"urn:tests:d\">\n"
476 " <k>val2</k>\n"
477 " <cont>\n"
478 " <l2>2</l2>\n"
479 " </cont>\n"
480 " <l4>2</l4>\n"
481 " <lt3>\n"
482 " <kk>val1</kk>\n"
483 " <l3>1</l3>\n"
484 " </lt3>\n"
485 " <lt3>\n"
486 " <kk>val2</kk>\n"
487 " <l3>2</l3>\n"
488 " </lt3>\n"
489 "</lt2>\n"
490 "<lt2 xmlns=\"urn:tests:d\">\n"
491 " <k>val3</k>\n"
492 " <cont>\n"
493 " <l2>3</l2>\n"
494 " </cont>\n"
495 " <l4>3</l4>\n"
496 " <lt3>\n"
497 " <kk>val1</kk>\n"
498 " <l3>2</l3>\n"
499 " </lt3>\n"
500 "</lt2>\n"
501 "<lt2 xmlns=\"urn:tests:d\">\n"
502 " <k>val4</k>\n"
503 " <cont>\n"
504 " <l2>4</l2>\n"
505 " </cont>\n"
506 " <l4>4</l4>\n"
507 " <lt3>\n"
508 " <kk>val1</kk>\n"
509 " <l3>3</l3>\n"
510 " </lt3>\n"
511 "</lt2>\n"
512 "<lt2 xmlns=\"urn:tests:d\">\n"
513 " <k>val5</k>\n"
514 " <cont>\n"
515 " <l2>5</l2>\n"
516 " </cont>\n"
517 " <l4>5</l4>\n"
518 " <lt3>\n"
519 " <kk>val1</kk>\n"
520 " <l3>3</l3>\n"
521 " </lt3>\n"
522 "</lt2>", tree);
523 lyd_free_all(tree);
524
525 CHECK_PARSE_LYD_PARAM("<lt2 xmlns=\"urn:tests:d\">\n"
526 " <k>val1</k>\n"
527 " <cont>\n"
528 " <l2>1</l2>\n"
529 " </cont>\n"
530 " <l4>1</l4>\n"
531 "</lt2>\n"
532 "<lt2 xmlns=\"urn:tests:d\">\n"
533 " <k>val2</k>\n"
534 " <cont>\n"
535 " <l2>2</l2>\n"
536 " </cont>\n"
537 " <lt3>\n"
538 " <kk>val1</kk>\n"
539 " <l3>1</l3>\n"
540 " </lt3>\n"
541 " <lt3>\n"
542 " <kk>val2</kk>\n"
543 " <l3>2</l3>\n"
544 " </lt3>\n"
545 " <lt3>\n"
546 " <kk>val3</kk>\n"
547 " <l3>1</l3>\n"
548 " </lt3>\n"
549 "</lt2>\n"
550 "<lt2 xmlns=\"urn:tests:d\">\n"
551 " <k>val3</k>\n"
552 " <cont>\n"
553 " <l2>3</l2>\n"
554 " </cont>\n"
555 " <l4>1</l4>\n"
556 " <lt3>\n"
557 " <kk>val1</kk>\n"
558 " <l3>2</l3>\n"
559 " </lt3>\n"
560 "</lt2>\n"
561 "<lt2 xmlns=\"urn:tests:d\">\n"
562 " <k>val4</k>\n"
563 " <cont>\n"
564 " <l2>4</l2>\n"
565 " </cont>\n"
566 " <lt3>\n"
567 " <kk>val1</kk>\n"
568 " <l3>3</l3>\n"
569 " </lt3>\n"
570 "</lt2>\n"
571 "<lt2 xmlns=\"urn:tests:d\">\n"
572 " <k>val5</k>\n"
573 " <cont>\n"
574 " <l2>5</l2>\n"
575 " </cont>\n"
576 " <lt3>\n"
577 " <kk>val1</kk>\n"
578 " <l3>3</l3>\n"
579 " </lt3>\n"
580 "</lt2>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskoe9391c72021-10-05 10:04:56 +0200581 CHECK_LOG_CTX_APPTAG("Unique data leaf(s) \"l3\" not satisfied in \"/d:lt2[k='val2']/lt3[kk='val3']\" and "
582 "\"/d:lt2[k='val2']/lt3[kk='val1']\".",
Michal Vaskodbf3e652022-10-21 08:46:25 +0200583 "Data location \"/d:lt2[k='val2']/lt3[kk='val1']\".", "data-not-unique");
Radek Iša56ca9e42020-09-08 18:42:00 +0200584
585 CHECK_PARSE_LYD_PARAM("<lt2 xmlns=\"urn:tests:d\">\n"
586 " <k>val1</k>\n"
587 " <cont>\n"
588 " <l2>1</l2>\n"
589 " </cont>\n"
590 " <l4>1</l4>\n"
591 "</lt2>\n"
592 "<lt2 xmlns=\"urn:tests:d\">\n"
593 " <k>val2</k>\n"
594 " <cont>\n"
595 " <l2>2</l2>\n"
596 " </cont>\n"
597 " <l4>2</l4>\n"
598 "</lt2>\n"
599 "<lt2 xmlns=\"urn:tests:d\">\n"
600 " <k>val3</k>\n"
601 " <cont>\n"
602 " <l2>3</l2>\n"
603 " </cont>\n"
604 " <l4>3</l4>\n"
605 "</lt2>\n"
606 "<lt2 xmlns=\"urn:tests:d\">\n"
607 " <k>val4</k>\n"
608 " <cont>\n"
609 " <l2>2</l2>\n"
610 " </cont>\n"
611 " <l4>2</l4>\n"
612 "</lt2>\n"
613 "<lt2 xmlns=\"urn:tests:d\">\n"
614 " <k>val5</k>\n"
615 " <cont>\n"
616 " <l2>5</l2>\n"
617 " </cont>\n"
618 " <l4>5</l4>\n"
619 "</lt2>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskoe9391c72021-10-05 10:04:56 +0200620 CHECK_LOG_CTX_APPTAG("Unique data leaf(s) \"cont/l2 l4\" not satisfied in \"/d:lt2[k='val4']\" and \"/d:lt2[k='val2']\".",
Michal Vaskodbf3e652022-10-21 08:46:25 +0200621 "Data location \"/d:lt2[k='val2']\".", "data-not-unique");
Radek Iša56ca9e42020-09-08 18:42:00 +0200622
623 CHECK_PARSE_LYD_PARAM("<lt2 xmlns=\"urn:tests:d\">\n"
624 " <k>val1</k>\n"
625 " <cont>\n"
626 " <l2>1</l2>\n"
627 " </cont>\n"
628 " <l4>1</l4>\n"
629 " <l5>1</l5>\n"
630 " <l6>1</l6>\n"
631 "</lt2>\n"
632 "<lt2 xmlns=\"urn:tests:d\">\n"
633 " <k>val2</k>\n"
634 " <cont>\n"
635 " <l2>2</l2>\n"
636 " </cont>\n"
637 " <l4>1</l4>\n"
638 " <l5>1</l5>\n"
639 "</lt2>\n"
640 "<lt2 xmlns=\"urn:tests:d\">\n"
641 " <k>val3</k>\n"
642 " <cont>\n"
643 " <l2>3</l2>\n"
644 " </cont>\n"
645 " <l4>1</l4>\n"
646 " <l5>3</l5>\n"
647 " <l6>3</l6>\n"
648 "</lt2>\n"
649 "<lt2 xmlns=\"urn:tests:d\">\n"
650 " <k>val4</k>\n"
651 " <cont>\n"
652 " <l2>4</l2>\n"
653 " </cont>\n"
654 " <l4>1</l4>\n"
655 " <l6>1</l6>\n"
656 "</lt2>\n"
657 "<lt2 xmlns=\"urn:tests:d\">\n"
658 " <k>val5</k>\n"
659 " <cont>\n"
660 " <l2>5</l2>\n"
661 " </cont>\n"
662 " <l4>1</l4>\n"
663 " <l5>3</l5>\n"
664 " <l6>3</l6>\n"
665 "</lt2>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskoe9391c72021-10-05 10:04:56 +0200666 CHECK_LOG_CTX_APPTAG("Unique data leaf(s) \"l5 l6\" not satisfied in \"/d:lt2[k='val5']\" and \"/d:lt2[k='val3']\".",
Michal Vaskodbf3e652022-10-21 08:46:25 +0200667 "Data location \"/d:lt2[k='val3']\".", "data-not-unique");
Radek Iša56ca9e42020-09-08 18:42:00 +0200668}
669
670static void
671test_dup(void **state)
672{
673 struct lyd_node *tree;
674 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100675 "module e {\n"
676 " namespace urn:tests:e;\n"
677 " prefix e;\n"
678 " yang-version 1.1;\n"
679 "\n"
680 " choice choic {\n"
681 " leaf a {\n"
682 " type string;\n"
683 " }\n"
684 " case b {\n"
685 " leaf-list l {\n"
686 " type string;\n"
687 " }\n"
688 " }\n"
689 " }\n"
690 " list lt {\n"
691 " key \"k\";\n"
692 " leaf k {\n"
693 " type string;\n"
694 " }\n"
695 " }\n"
696 " leaf d {\n"
697 " type uint32;\n"
698 " }\n"
699 " leaf-list ll {\n"
700 " type string;\n"
701 " }\n"
702 " container cont {\n"
703 " list lt {\n"
704 " key \"k\";\n"
705 " leaf k {\n"
706 " type string;\n"
707 " }\n"
708 " }\n"
709 " leaf d {\n"
710 " type uint32;\n"
711 " }\n"
712 " leaf-list ll {\n"
713 " type string;\n"
714 " }\n"
715 " leaf-list ll2 {\n"
716 " type enumeration {\n"
717 " enum one;\n"
718 " enum two;\n"
719 " }\n"
720 " }\n"
721 " }\n"
722 "}";
Radek Iša56ca9e42020-09-08 18:42:00 +0200723
724 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
725
726 CHECK_PARSE_LYD_PARAM("<d xmlns=\"urn:tests:e\">25</d><d xmlns=\"urn:tests:e\">50</d>",
727 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +0200728 CHECK_LOG_CTX("Duplicate instance of \"d\".", "Data location \"/e:d\".");
Radek Iša56ca9e42020-09-08 18:42:00 +0200729
730 CHECK_PARSE_LYD_PARAM("<lt xmlns=\"urn:tests:e\"><k>A</k></lt>"
731 "<lt xmlns=\"urn:tests:e\"><k>B</k></lt>"
732 "<lt xmlns=\"urn:tests:e\"><k>A</k></lt>",
733 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +0200734 CHECK_LOG_CTX("Duplicate instance of \"lt\".", "Data location \"/e:lt[k='A']\".");
Radek Iša56ca9e42020-09-08 18:42:00 +0200735
736 CHECK_PARSE_LYD_PARAM("<ll xmlns=\"urn:tests:e\">A</ll>"
737 "<ll xmlns=\"urn:tests:e\">B</ll>"
738 "<ll xmlns=\"urn:tests:e\">B</ll>",
739 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +0200740 CHECK_LOG_CTX("Duplicate instance of \"ll\".", "Data location \"/e:ll[.='B']\".");
Radek Iša56ca9e42020-09-08 18:42:00 +0200741
742 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:e\"></cont><cont xmlns=\"urn:tests:e\"/>",
743 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +0200744 CHECK_LOG_CTX("Duplicate instance of \"cont\".", "Data location \"/e:cont\".");
Radek Iša56ca9e42020-09-08 18:42:00 +0200745
746 /* same tests again but using hashes */
747 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:e\"><d>25</d><d>50</d><ll>1</ll><ll>2</ll><ll>3</ll><ll>4</ll></cont>",
748 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +0200749 CHECK_LOG_CTX("Duplicate instance of \"d\".", "Data location \"/e:cont/d\", line number 1.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200750
751 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:e\"><ll>1</ll><ll>2</ll><ll>3</ll><ll>4</ll>"
752 "<lt><k>a</k></lt>"
753 "<lt><k>b</k></lt>"
754 "<lt><k>c</k></lt>"
755 "<lt><k>d</k></lt>"
756 "<lt><k>c</k></lt></cont>",
757 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +0200758 CHECK_LOG_CTX("Duplicate instance of \"lt\".", "Data location \"/e:cont/lt[k='c']\", line number 1.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200759
760 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:e\"><ll>1</ll><ll>2</ll><ll>3</ll><ll>4</ll>"
761 "<ll>a</ll><ll>b</ll><ll>c</ll><ll>d</ll><ll>d</ll></cont>",
762 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +0200763 CHECK_LOG_CTX("Duplicate instance of \"ll\".", "Data location \"/e:cont/ll[.='d']\", line number 1.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200764
765 /* cases */
766 CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:e\">a</l>"
767 "<l xmlns=\"urn:tests:e\">b</l>"
768 "<l xmlns=\"urn:tests:e\">c</l>"
769 "<l xmlns=\"urn:tests:e\">b</l>",
770 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +0200771 CHECK_LOG_CTX("Duplicate instance of \"l\".", "Data location \"/e:l[.='b']\".");
Radek Iša56ca9e42020-09-08 18:42:00 +0200772
773 CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:e\">a</l><l xmlns=\"urn:tests:e\">b</l>"
774 "<l xmlns=\"urn:tests:e\">c</l>"
775 "<a xmlns=\"urn:tests:e\">aa</a>",
776 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vasko959f8d82022-06-16 07:51:50 +0200777 CHECK_LOG_CTX("Data for both cases \"a\" and \"b\" exist.", "Schema location \"/e:choic\".");
Radek Iša56ca9e42020-09-08 18:42:00 +0200778}
779
780static void
781test_defaults(void **state)
782{
783 struct lyd_node *tree, *node, *diff;
Michal Vasko4de7d072021-07-09 09:13:18 +0200784 struct lys_module *mod;
Radek Iša56ca9e42020-09-08 18:42:00 +0200785 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100786 "module f {\n"
787 " namespace urn:tests:f;\n"
788 " prefix f;\n"
789 " yang-version 1.1;\n"
790 "\n"
791 " choice choic {\n"
792 " default \"c\";\n"
793 " leaf a {\n"
794 " type string;\n"
795 " }\n"
796 " case b {\n"
797 " leaf l {\n"
798 " type string;\n"
799 " }\n"
800 " }\n"
801 " case c {\n"
802 " leaf-list ll1 {\n"
803 " type string;\n"
804 " default \"def1\";\n"
805 " default \"def2\";\n"
806 " default \"def3\";\n"
807 " }\n"
808 " }\n"
809 " }\n"
810 " leaf d {\n"
811 " type uint32;\n"
812 " default 15;\n"
813 " }\n"
Radek Krejci7be7b9f2021-02-24 11:46:27 +0100814 " leaf dd {\n"
815 " type uint32;\n"
816 " when '../d = 666';\n"
817 " default 15;\n"
818 " }\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100819 " leaf-list ll2 {\n"
820 " type string;\n"
821 " default \"dflt1\";\n"
822 " default \"dflt2\";\n"
823 " }\n"
824 " container cont {\n"
825 " choice choic {\n"
826 " default \"c\";\n"
827 " leaf a {\n"
828 " type string;\n"
829 " }\n"
830 " case b {\n"
831 " leaf l {\n"
832 " type string;\n"
833 " }\n"
834 " }\n"
835 " case c {\n"
836 " leaf-list ll1 {\n"
837 " type string;\n"
838 " default \"def1\";\n"
839 " default \"def2\";\n"
840 " default \"def3\";\n"
841 " }\n"
842 " }\n"
843 " }\n"
844 " leaf d {\n"
845 " type uint32;\n"
846 " default 15;\n"
847 " }\n"
Radek Krejci7be7b9f2021-02-24 11:46:27 +0100848 " leaf dd {\n"
849 " type uint32;\n"
850 " when '../d = 666';\n"
851 " default 15;\n"
852 " }\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100853 " leaf-list ll2 {\n"
854 " type string;\n"
855 " default \"dflt1\";\n"
856 " default \"dflt2\";\n"
857 " }\n"
858 " }\n"
859 "}";
Radek Iša56ca9e42020-09-08 18:42:00 +0200860
861 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
862
863 assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
864 assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf-with-defaults", "2011-06-01", NULL));\
865
866 /* get defaults */
867 tree = NULL;
868 assert_int_equal(lyd_validate_module(&tree, mod, 0, &diff), LY_SUCCESS);
869 assert_non_null(tree);
870 assert_non_null(diff);
871
872 /* check all defaults exist */
873 CHECK_LYD_STRING_PARAM(tree,
874 "<ll1 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>\n"
875 "<ll1 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>\n"
876 "<ll1 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def3</ll1>\n"
877 "<d xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
878 "<ll2 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
879 "<ll2 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
880 "<cont xmlns=\"urn:tests:f\">\n"
881 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>\n"
882 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>\n"
883 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def3</ll1>\n"
884 " <d xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
885 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
886 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
887 "</cont>\n",
888 LYD_XML, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_WITHSIBLINGS);
889
890 /* check diff */
891 CHECK_LYD_STRING_PARAM(diff,
892 "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">def1</ll1>\n"
893 "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">def2</ll1>\n"
894 "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">def3</ll1>\n"
895 "<d xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">15</d>\n"
896 "<ll2 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">dflt1</ll2>\n"
897 "<ll2 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">dflt2</ll2>\n"
898 "<cont xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">\n"
899 " <ll1 yang:operation=\"create\">def1</ll1>\n"
900 " <ll1 yang:operation=\"create\">def2</ll1>\n"
901 " <ll1 yang:operation=\"create\">def3</ll1>\n"
902 " <d yang:operation=\"create\">15</d>\n"
903 " <ll2 yang:operation=\"create\">dflt1</ll2>\n"
904 " <ll2 yang:operation=\"create\">dflt2</ll2>\n"
905 "</cont>\n",
906 LYD_XML, LYD_PRINT_WD_ALL | LYD_PRINT_WITHSIBLINGS);
907 lyd_free_all(diff);
908
909 /* create another explicit case and validate */
910 assert_int_equal(lyd_new_term(NULL, mod, "l", "value", 0, &node), LY_SUCCESS);
911 assert_int_equal(lyd_insert_sibling(tree, node, &tree), LY_SUCCESS);
912 assert_int_equal(lyd_validate_all(&tree, UTEST_LYCTX, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
913
914 /* check data tree */
915 CHECK_LYD_STRING_PARAM(tree,
916 "<l xmlns=\"urn:tests:f\">value</l>\n"
917 "<d xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
918 "<ll2 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
919 "<ll2 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
920 "<cont xmlns=\"urn:tests:f\">\n"
921 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>\n"
922 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>\n"
923 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def3</ll1>\n"
924 " <d xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
925 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
926 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
927 "</cont>\n",
928 LYD_XML, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_WITHSIBLINGS);
929
930 /* check diff */
931 CHECK_LYD_STRING_PARAM(diff,
932 "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">def1</ll1>\n"
933 "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">def2</ll1>\n"
934 "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">def3</ll1>\n",
935 LYD_XML, LYD_PRINT_WD_ALL | LYD_PRINT_WITHSIBLINGS);
936 lyd_free_all(diff);
937
938 /* create explicit leaf-list and leaf and validate */
939 assert_int_equal(lyd_new_term(NULL, mod, "d", "15", 0, &node), LY_SUCCESS);
940 assert_int_equal(lyd_insert_sibling(tree, node, &tree), LY_SUCCESS);
941 assert_int_equal(lyd_new_term(NULL, mod, "ll2", "dflt2", 0, &node), LY_SUCCESS);
942 assert_int_equal(lyd_insert_sibling(tree, node, &tree), LY_SUCCESS);
943 assert_int_equal(lyd_validate_all(&tree, UTEST_LYCTX, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
944
945 /* check data tree */
946 CHECK_LYD_STRING_PARAM(tree,
947 "<l xmlns=\"urn:tests:f\">value</l>\n"
948 "<d xmlns=\"urn:tests:f\">15</d>\n"
949 "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>\n"
950 "<cont xmlns=\"urn:tests:f\">\n"
951 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>\n"
952 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>\n"
953 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def3</ll1>\n"
954 " <d xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
955 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
956 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
957 "</cont>\n",
958 LYD_XML, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_WITHSIBLINGS);
959
960 /* check diff */
961 CHECK_LYD_STRING_PARAM(diff,
962 "<d xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">15</d>\n"
963 "<ll2 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">dflt1</ll2>\n"
964 "<ll2 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">dflt2</ll2>\n",
965 LYD_XML, LYD_PRINT_WD_ALL | LYD_PRINT_WITHSIBLINGS);
966 lyd_free_all(diff);
967
968 /* create first explicit container, which should become implicit */
969 assert_int_equal(lyd_new_inner(NULL, mod, "cont", 0, &node), LY_SUCCESS);
970 assert_int_equal(lyd_insert_sibling(tree, node, &tree), LY_SUCCESS);
971 assert_int_equal(lyd_validate_all(&tree, UTEST_LYCTX, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
972
973 /* check data tree */
974 CHECK_LYD_STRING_PARAM(tree,
975 "<l xmlns=\"urn:tests:f\">value</l>\n"
976 "<d xmlns=\"urn:tests:f\">15</d>\n"
977 "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>\n"
978 "<cont xmlns=\"urn:tests:f\">\n"
979 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>\n"
980 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>\n"
981 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def3</ll1>\n"
982 " <d xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
983 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
984 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
985 "</cont>\n",
986 LYD_XML, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_WITHSIBLINGS);
987 /* check diff */
988 assert_null(diff);
989
990 /* create second explicit container, which should become implicit, so the first tree node should be removed */
991 assert_int_equal(lyd_new_inner(NULL, mod, "cont", 0, &node), LY_SUCCESS);
992 assert_int_equal(lyd_insert_sibling(tree, node, &tree), LY_SUCCESS);
993 assert_int_equal(lyd_validate_all(&tree, UTEST_LYCTX, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
994
995 /* check data tree */
996 CHECK_LYD_STRING_PARAM(tree,
997 "<l xmlns=\"urn:tests:f\">value</l>\n"
998 "<d xmlns=\"urn:tests:f\">15</d>\n"
999 "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>\n"
1000 "<cont xmlns=\"urn:tests:f\">\n"
1001 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>\n"
1002 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>\n"
1003 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def3</ll1>\n"
1004 " <d xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
1005 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
1006 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
1007 "</cont>\n",
1008 LYD_XML, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_WITHSIBLINGS);
1009 /* check diff */
1010 assert_null(diff);
1011
1012 /* similar changes for nested defaults */
1013 assert_int_equal(lyd_new_term(tree->prev, NULL, "ll1", "def3", 0, NULL), LY_SUCCESS);
1014 assert_int_equal(lyd_new_term(tree->prev, NULL, "d", "5", 0, NULL), LY_SUCCESS);
1015 assert_int_equal(lyd_new_term(tree->prev, NULL, "ll2", "non-dflt", 0, NULL), LY_SUCCESS);
1016 assert_int_equal(lyd_validate_all(&tree, UTEST_LYCTX, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
1017
1018 /* check data tree */
1019 CHECK_LYD_STRING_PARAM(tree,
1020 "<l xmlns=\"urn:tests:f\">value</l>\n"
1021 "<d xmlns=\"urn:tests:f\">15</d>\n"
1022 "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>\n"
1023 "<cont xmlns=\"urn:tests:f\">\n"
1024 " <ll1>def3</ll1>\n"
1025 " <d>5</d>\n"
1026 " <ll2>non-dflt</ll2>\n"
1027 "</cont>\n",
1028 LYD_XML, LYD_PRINT_WITHSIBLINGS);
1029
1030 /* check diff */
1031 CHECK_LYD_STRING_PARAM(diff,
1032 "<cont xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
1033 " <ll1 yang:operation=\"delete\">def1</ll1>\n"
1034 " <ll1 yang:operation=\"delete\">def2</ll1>\n"
1035 " <ll1 yang:operation=\"delete\">def3</ll1>\n"
1036 " <d yang:operation=\"delete\">15</d>\n"
1037 " <ll2 yang:operation=\"delete\">dflt1</ll2>\n"
1038 " <ll2 yang:operation=\"delete\">dflt2</ll2>\n"
1039 "</cont>\n",
1040 LYD_XML, LYD_PRINT_WD_ALL | LYD_PRINT_WITHSIBLINGS);
1041 lyd_free_all(diff);
1042 lyd_free_all(tree);
Radek Krejci7be7b9f2021-02-24 11:46:27 +01001043
1044 /* check data tree - when enabled node */
1045 CHECK_PARSE_LYD_PARAM("<d xmlns=\"urn:tests:f\">666</d><cont xmlns=\"urn:tests:f\"><d>666</d></cont>",
1046 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
1047 CHECK_LYD_STRING_PARAM(tree,
1048 "<ll1 xmlns=\"urn:tests:f\">def1</ll1>\n"
1049 "<ll1 xmlns=\"urn:tests:f\">def2</ll1>\n"
1050 "<ll1 xmlns=\"urn:tests:f\">def3</ll1>\n"
1051 "<d xmlns=\"urn:tests:f\">666</d>\n"
1052 "<dd xmlns=\"urn:tests:f\">15</dd>\n"
1053 "<ll2 xmlns=\"urn:tests:f\">dflt1</ll2>\n"
1054 "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>\n"
1055 "<cont xmlns=\"urn:tests:f\">\n"
1056 " <ll1>def1</ll1>\n"
1057 " <ll1>def2</ll1>\n"
1058 " <ll1>def3</ll1>\n"
1059 " <d>666</d>\n"
1060 " <dd>15</dd>\n"
1061 " <ll2>dflt1</ll2>\n"
1062 " <ll2>dflt2</ll2>\n"
1063 "</cont>\n",
1064 LYD_XML, LYD_PRINT_WD_ALL | LYD_PRINT_WITHSIBLINGS);
1065 lyd_free_all(tree);
Radek Iša56ca9e42020-09-08 18:42:00 +02001066}
1067
1068static void
1069test_state(void **state)
1070{
1071 const char *data;
1072 struct lyd_node *tree;
1073 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001074 "module h {\n"
1075 " namespace urn:tests:h;\n"
1076 " prefix h;\n"
1077 " yang-version 1.1;\n"
1078 "\n"
1079 " container cont {\n"
1080 " container cont2 {\n"
1081 " config false;\n"
1082 " leaf l {\n"
1083 " type string;\n"
1084 " }\n"
1085 " }\n"
1086 " }\n"
1087 "}";
Radek Iša56ca9e42020-09-08 18:42:00 +02001088
1089 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
1090
1091 data = "<cont xmlns=\"urn:tests:h\">\n"
1092 " <cont2>\n"
1093 " <l>val</l>\n"
1094 " </cont2>\n"
1095 "</cont>\n";
1096 CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_NO_STATE, 0, LY_EVALID, tree);
Michal Vasko224e7772021-02-18 14:22:33 +01001097 CHECK_LOG_CTX("Unexpected data state node \"cont2\" found.",
Michal Vaskoa4dfb3c2022-10-25 14:59:31 +02001098 "Data location \"/h:cont/cont2\", line number 3.");
Radek Iša56ca9e42020-09-08 18:42:00 +02001099
1100 CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
1101 assert_int_equal(LY_EVALID, lyd_validate_all(&tree, NULL, LYD_VALIDATE_PRESENT | LYD_VALIDATE_NO_STATE, NULL));
Michal Vasko224e7772021-02-18 14:22:33 +01001102 CHECK_LOG_CTX("Unexpected data state node \"cont2\" found.",
Michal Vaskodbf3e652022-10-21 08:46:25 +02001103 "Data location \"/h:cont/cont2\".");
Radek Iša56ca9e42020-09-08 18:42:00 +02001104 lyd_free_all(tree);
1105}
1106
1107static void
1108test_must(void **state)
1109{
1110 struct lyd_node *tree;
1111 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001112 "module i {\n"
1113 " namespace urn:tests:i;\n"
1114 " prefix i;\n"
1115 " yang-version 1.1;\n"
1116 "\n"
1117 " container cont {\n"
1118 " leaf l {\n"
1119 " type string;\n"
1120 " }\n"
1121 " leaf l2 {\n"
1122 " must \"../l = 'right'\";\n"
1123 " type string;\n"
1124 " }\n"
Michal Vaskoe9391c72021-10-05 10:04:56 +02001125 " leaf l3 {\n"
1126 " must \"../l = 'left'\" {\n"
1127 " error-app-tag \"not-left\";\n"
1128 " error-message \"l leaf is not left\";\n"
1129 " }\n"
1130 " type string;\n"
1131 " }\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001132 " }\n"
1133 "}";
Michal Vaskocde73ac2019-11-14 16:10:27 +01001134
Radek Iša56ca9e42020-09-08 18:42:00 +02001135 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
Michal Vaskocde73ac2019-11-14 16:10:27 +01001136
Radek Iša56ca9e42020-09-08 18:42:00 +02001137 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:i\">\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001138 " <l>wrong</l>\n"
1139 " <l2>val</l2>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001140 "</cont>\n", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskoe9391c72021-10-05 10:04:56 +02001141 CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.",
Michal Vaskodbf3e652022-10-21 08:46:25 +02001142 "Data location \"/i:cont/l2\".", "must-violation");
Michal Vaskocc048b22020-03-27 15:52:38 +01001143
Radek Iša56ca9e42020-09-08 18:42:00 +02001144 LYD_TREE_CREATE("<cont xmlns=\"urn:tests:i\">\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001145 " <l>right</l>\n"
1146 " <l2>val</l2>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001147 "</cont>\n", tree);
1148 lyd_free_all(tree);
Michal Vaskoe9391c72021-10-05 10:04:56 +02001149
1150 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:i\">\n"
1151 " <l>wrong</l>\n"
1152 " <l3>val</l3>\n"
1153 "</cont>\n", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Michal Vaskodbf3e652022-10-21 08:46:25 +02001154 CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/i:cont/l3\".", "not-left");
Michal Vaskocc048b22020-03-27 15:52:38 +01001155}
1156
Michal Vaskod027f382023-02-10 09:13:25 +01001157static void
1158test_multi_error(void **state)
1159{
1160 struct lyd_node *tree;
1161 const char *schema =
1162 "module ii {\n"
1163 " namespace urn:tests:ii;\n"
1164 " prefix ii;\n"
1165 " yang-version 1.1;\n"
1166 "\n"
1167 " container cont {\n"
1168 " leaf l {\n"
1169 " type string;\n"
1170 " }\n"
1171 " leaf l2 {\n"
1172 " must \"../l = 'right'\";\n"
1173 " type string;\n"
1174 " }\n"
1175 " leaf l3 {\n"
1176 " must \"../l = 'left'\" {\n"
1177 " error-app-tag \"not-left\";\n"
1178 " error-message \"l leaf is not left\";\n"
1179 " }\n"
1180 " type string;\n"
1181 " }\n"
1182 " leaf-list ll {\n"
1183 " type uint32;\n"
1184 " min-elements 2;\n"
1185 " }\n"
1186 " }\n"
1187 "}";
1188 const char *data;
1189
1190 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
1191
1192 /* xml */
1193 data =
1194 "<cont xmlns=\"urn:tests:ii\">\n"
1195 " <l>wrong</l>\n"
1196 " <l>wrong2</l>\n"
1197 " <l2>val</l2>\n"
1198 " <l3>val</l3>\n"
1199 " <ll>ahoy</ll>\n"
1200 "</cont>\n";
1201 CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT | LYD_VALIDATE_MULTI_ERROR, LY_EVALID, tree);
1202 CHECK_LOG_CTX_APPTAG("Too few \"ll\" instances.", "Schema location \"/ii:cont/ll\".", "too-few-elements");
1203 CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/ii:cont/l3\".", "not-left");
1204 CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "Data location \"/ii:cont/l2\".", "must-violation");
Michal Vaskod027f382023-02-10 09:13:25 +01001205 CHECK_LOG_CTX_APPTAG("Invalid type uint32 value \"ahoy\".", "Data location \"/ii:cont/ll\", line number 6.", NULL);
1206
1207 /* json */
1208 data = "{\n"
1209 " \"ii:cont\": {\n"
1210 " \"l\": \"wrong\",\n"
1211 " \"l\": \"wrong2\",\n"
1212 " \"l2\": \"val\",\n"
1213 " \"l3\": \"val\",\n"
1214 " \"ll\": [\"ahoy\"]\n"
1215 " }\n"
1216 "}\n";
1217 CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT | LYD_VALIDATE_MULTI_ERROR, LY_EVALID, tree);
1218 CHECK_LOG_CTX_APPTAG("Too few \"ll\" instances.", "Schema location \"/ii:cont/ll\".", "too-few-elements");
1219 CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/ii:cont/l3\".", "not-left");
1220 CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "Data location \"/ii:cont/l2\".", "must-violation");
Michal Vaskod027f382023-02-10 09:13:25 +01001221 CHECK_LOG_CTX_APPTAG("Invalid non-number-encoded uint32 value \"ahoy\".", "Data location \"/ii:cont/ll\", line number 7.", NULL);
1222
1223 /* validation */
1224 data = "{\n"
1225 " \"ii:cont\": {\n"
1226 " \"l\": \"wrong\",\n"
1227 " \"l\": \"wrong2\",\n"
1228 " \"l2\": \"val\",\n"
1229 " \"l3\": \"val\",\n"
1230 " \"ll\": [25]\n"
1231 " }\n"
1232 "}\n";
1233 CHECK_PARSE_LYD_PARAM(data, LYD_JSON, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
1234 assert_int_equal(LY_EVALID, lyd_validate_all(&tree, NULL, LYD_VALIDATE_PRESENT | LYD_VALIDATE_MULTI_ERROR, NULL));
1235 lyd_free_tree(tree);
1236 CHECK_LOG_CTX_APPTAG("Too few \"ll\" instances.", "Schema location \"/ii:cont/ll\".", "too-few-elements");
1237 CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/ii:cont/l3\".", "not-left");
1238 CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "Data location \"/ii:cont/l2\".", "must-violation");
1239 CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\".", NULL);
Michal Vaskoa6139e02023-10-03 14:13:22 +02001240 CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\".", NULL);
Michal Vaskod027f382023-02-10 09:13:25 +01001241}
1242
Radek Iša56ca9e42020-09-08 18:42:00 +02001243const char *schema_j =
1244 "module j {\n"
1245 " namespace urn:tests:j;\n"
1246 " prefix j;\n"
1247 " yang-version 1.1;\n"
1248 "\n"
1249 " feature feat1;\n"
1250 "\n"
1251 " container cont {\n"
1252 " must \"false()\";\n"
1253 " list l1 {\n"
1254 " key \"k\";\n"
1255 " leaf k {\n"
1256 " type string;\n"
1257 " }\n"
1258 " action act {\n"
1259 " if-feature feat1;\n"
1260 " input {\n"
1261 " must \"../../lf1 = 'true'\";\n"
1262 " leaf lf2 {\n"
1263 " type leafref {\n"
1264 " path /lf3;\n"
1265 " }\n"
1266 " }\n"
1267 " }\n"
1268 " output {\n"
1269 " must \"../../lf1 = 'true2'\";\n"
1270 " leaf lf2 {\n"
1271 " type leafref {\n"
1272 " path /lf4;\n"
1273 " }\n"
1274 " }\n"
1275 " }\n"
1276 " }\n"
1277 " }\n"
1278 "\n"
1279 " leaf lf1 {\n"
1280 " type string;\n"
1281 " }\n"
1282 " }\n"
1283 "\n"
1284 " leaf lf3 {\n"
1285 " type string;\n"
1286 " }\n"
1287 "\n"
1288 " leaf lf4 {\n"
1289 " type string;\n"
1290 " }\n"
1291 "}";
1292const char *feats_j[] = {"feat1", NULL};
1293
Michal Vaskofea12c62020-03-30 11:00:15 +02001294static void
1295test_action(void **state)
1296{
Michal Vasko63f3d842020-07-08 10:10:14 +02001297 struct ly_in *in;
Michal Vaskofea12c62020-03-30 11:00:15 +02001298 struct lyd_node *tree, *op_tree;
Michal Vaskofea12c62020-03-30 11:00:15 +02001299
Radek Iša56ca9e42020-09-08 18:42:00 +02001300 UTEST_ADD_MODULE(schema_j, LYS_IN_YANG, feats_j, NULL);
Michal Vasko62af3692023-02-09 14:00:09 +01001301 UTEST_LOG_CTX_CLEAN;
Radek Iša56ca9e42020-09-08 18:42:00 +02001302
1303 assert_int_equal(LY_SUCCESS, ly_in_new_memory(
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001304 "<cont xmlns=\"urn:tests:j\">\n"
1305 " <l1>\n"
1306 " <k>val1</k>\n"
1307 " <act>\n"
1308 " <lf2>target</lf2>\n"
1309 " </act>\n"
1310 " </l1>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001311 "</cont>\n", &in));
Michal Vasko1e4c68e2021-02-18 15:03:01 +01001312 assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, &op_tree, NULL));
Michal Vaskofea12c62020-03-30 11:00:15 +02001313 assert_non_null(op_tree);
1314
1315 /* missing leafref */
Michal Vasko1e4c68e2021-02-18 15:03:01 +01001316 assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_TYPE_RPC_YANG, NULL));
Michal Vasko5edfefd2022-08-05 10:07:11 +02001317 CHECK_LOG_CTX("Invalid leafref value \"target\" - no target instance \"/lf3\" with the same value.",
Michal Vaskodbf3e652022-10-21 08:46:25 +02001318 "Data location \"/j:cont/l1[k='val1']/act/lf2\".");
Michal Vasko63f3d842020-07-08 10:10:14 +02001319 ly_in_free(in, 0);
Michal Vaskofea12c62020-03-30 11:00:15 +02001320
Radek Iša56ca9e42020-09-08 18:42:00 +02001321 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:j\">\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001322 " <lf1>not true</lf1>\n"
1323 "</cont>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001324 "<lf3 xmlns=\"urn:tests:j\">target</lf3>\n",
1325 LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
Michal Vaskofea12c62020-03-30 11:00:15 +02001326
Michal Vaskofea12c62020-03-30 11:00:15 +02001327 /* input must false */
Michal Vasko1e4c68e2021-02-18 15:03:01 +01001328 assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_TYPE_RPC_YANG, NULL));
Radek Krejci2efc45b2020-12-22 16:25:44 +01001329 CHECK_LOG_CTX("Must condition \"../../lf1 = 'true'\" not satisfied.",
Michal Vasko959f8d82022-06-16 07:51:50 +02001330 "Data location \"/j:cont/l1[k='val1']/act\".");
Michal Vaskofea12c62020-03-30 11:00:15 +02001331
Radek Iša56ca9e42020-09-08 18:42:00 +02001332 lyd_free_all(tree);
1333 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:j\">\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001334 " <lf1>true</lf1>\n"
1335 "</cont>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001336 "<lf3 xmlns=\"urn:tests:j\">target</lf3>\n",
1337 LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
Michal Vaskofea12c62020-03-30 11:00:15 +02001338
1339 /* success */
Michal Vasko1e4c68e2021-02-18 15:03:01 +01001340 assert_int_equal(LY_SUCCESS, lyd_validate_op(op_tree, tree, LYD_TYPE_RPC_YANG, NULL));
Michal Vaskofea12c62020-03-30 11:00:15 +02001341
Michal Vaskocb7526d2020-03-30 15:08:26 +02001342 lyd_free_tree(op_tree);
1343 lyd_free_siblings(tree);
Michal Vaskocb7526d2020-03-30 15:08:26 +02001344}
1345
1346static void
aPiecek18a844e2021-08-10 11:06:24 +02001347test_rpc(void **state)
1348{
1349 const char *schema, *data;
1350 struct ly_in *in;
1351 struct lyd_node *tree;
1352
1353 /* Testing constraint violation in RPC. */
1354 schema =
1355 "module val-str {\n"
1356 " namespace \"urn:vstr\";\n"
1357 " prefix v;\n"
1358 "\n"
1359 " rpc modify-user-password {\n"
1360 " input {\n"
1361 " leaf old-password {\n"
1362 " type string {\n"
1363 " length \"4..8\";\n"
1364 " }\n"
1365 " }\n"
1366 " leaf new-password {\n"
1367 " type string {\n"
1368 " length \"4..8\";\n"
1369 " }\n"
1370 " }\n"
1371 " }\n"
1372 " }\n"
1373 "}\n";
1374 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
1375 data =
1376 "<modify-user-password xmlns=\"urn:vstr\">\n"
1377 " <old-password>12345</old-password>\n"
1378 " <new-password>123</new-password>\n"
1379 "</modify-user-password>";
1380 assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
Michal Vasko140ede92022-05-10 09:27:30 +02001381 assert_int_equal(LY_EVALID, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_RPC_YANG, &tree, NULL));
Michal Vaskodbf3e652022-10-21 08:46:25 +02001382 CHECK_LOG_CTX("Unsatisfied length - string \"123\" length is not allowed.",
Michal Vaskoa4dfb3c2022-10-25 14:59:31 +02001383 "Data location \"/val-str:modify-user-password/new-password\", line number 3.");
aPiecek18a844e2021-08-10 11:06:24 +02001384 ly_in_free(in, 0);
aPiecek18a844e2021-08-10 11:06:24 +02001385}
1386
1387static void
Michal Vaskocb7526d2020-03-30 15:08:26 +02001388test_reply(void **state)
1389{
Michal Vasko63f3d842020-07-08 10:10:14 +02001390 struct ly_in *in;
Michal Vasko2552ea32020-12-08 15:32:34 +01001391 struct lyd_node *tree, *op_tree;
Michal Vaskocb7526d2020-03-30 15:08:26 +02001392
Radek Iša56ca9e42020-09-08 18:42:00 +02001393 UTEST_ADD_MODULE(schema_j, LYS_IN_YANG, feats_j, NULL);
Michal Vasko62af3692023-02-09 14:00:09 +01001394 UTEST_LOG_CTX_CLEAN;
Radek Iša56ca9e42020-09-08 18:42:00 +02001395
1396 assert_int_equal(LY_SUCCESS, ly_in_new_memory(
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001397 "<cont xmlns=\"urn:tests:j\">\n"
1398 " <l1>\n"
1399 " <k>val1</k>\n"
1400 " <act>\n"
1401 " <lf2>target</lf2>\n"
1402 " </act>\n"
1403 " </l1>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001404 "</cont>\n", &in));
Michal Vasko1e4c68e2021-02-18 15:03:01 +01001405 assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_REPLY_YANG, &op_tree, NULL));
Michal Vaskocb7526d2020-03-30 15:08:26 +02001406 assert_non_null(op_tree);
Michal Vasko63f3d842020-07-08 10:10:14 +02001407 ly_in_free(in, 0);
Michal Vaskocb7526d2020-03-30 15:08:26 +02001408
1409 /* missing leafref */
Michal Vasko1e4c68e2021-02-18 15:03:01 +01001410 assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_TYPE_REPLY_YANG, NULL));
Michal Vasko5edfefd2022-08-05 10:07:11 +02001411 CHECK_LOG_CTX("Invalid leafref value \"target\" - no target instance \"/lf4\" with the same value.",
Michal Vaskodbf3e652022-10-21 08:46:25 +02001412 "Data location \"/j:cont/l1[k='val1']/act/lf2\".");
Michal Vaskocb7526d2020-03-30 15:08:26 +02001413
Radek Iša56ca9e42020-09-08 18:42:00 +02001414 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:j\">\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001415 " <lf1>not true</lf1>\n"
1416 "</cont>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001417 "<lf4 xmlns=\"urn:tests:j\">target</lf4>\n",
1418 LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
Michal Vaskocb7526d2020-03-30 15:08:26 +02001419
Michal Vaskocb7526d2020-03-30 15:08:26 +02001420 /* input must false */
Michal Vasko1e4c68e2021-02-18 15:03:01 +01001421 assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_TYPE_REPLY_YANG, NULL));
Michal Vasko959f8d82022-06-16 07:51:50 +02001422 CHECK_LOG_CTX("Must condition \"../../lf1 = 'true2'\" not satisfied.", "Data location \"/j:cont/l1[k='val1']/act\".");
Michal Vaskocb7526d2020-03-30 15:08:26 +02001423
Radek Iša56ca9e42020-09-08 18:42:00 +02001424 lyd_free_all(tree);
1425 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:j\">\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001426 " <lf1>true2</lf1>\n"
1427 "</cont>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001428 "<lf4 xmlns=\"urn:tests:j\">target</lf4>\n",
1429 LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
Michal Vaskocb7526d2020-03-30 15:08:26 +02001430
1431 /* success */
Michal Vasko1e4c68e2021-02-18 15:03:01 +01001432 assert_int_equal(LY_SUCCESS, lyd_validate_op(op_tree, tree, LYD_TYPE_REPLY_YANG, NULL));
Michal Vaskocb7526d2020-03-30 15:08:26 +02001433
Michal Vaskofea12c62020-03-30 11:00:15 +02001434 lyd_free_tree(op_tree);
Radek Iša56ca9e42020-09-08 18:42:00 +02001435 lyd_free_all(tree);
Michal Vaskofea12c62020-03-30 11:00:15 +02001436}
1437
Michal Vasko8d151222021-07-22 12:12:41 +02001438static void
1439test_case(void **state)
1440{
1441 struct lyd_node *tree;
1442 const char *schema =
1443 "module k {\n"
1444 " namespace urn:tests:k;\n"
1445 " prefix k;\n"
1446 " yang-version 1.1;\n"
1447 "\n"
1448 " container ch {\n"
1449 " choice a0 {\n"
1450 " case v0 {\n"
1451 " leaf g0 {\n"
1452 " type string;\n"
1453 " }\n"
1454 " }\n"
1455 " case v1 {\n"
1456 " choice a1 {\n"
1457 " case r0 {\n"
1458 " leaf g1 {\n"
1459 " type string;\n"
1460 " }\n"
1461 " }\n"
1462 " case r1 {\n"
1463 " leaf g2 {\n"
1464 " type string;\n"
1465 " }\n"
1466 " leaf g3 {\n"
1467 " type string;\n"
1468 " }\n"
1469 " }\n"
1470 " case r2 {\n"
1471 " leaf g4 {\n"
1472 " type string;\n"
1473 " }\n"
1474 " }\n"
1475 " }\n"
1476 " }\n"
1477 " case v2 {\n"
1478 " choice a2 {\n"
1479 " case y0 {\n"
1480 " leaf g5 {\n"
1481 " type string;\n"
1482 " }\n"
1483 " }\n"
1484 " case y1 {\n"
1485 " leaf g6 {\n"
1486 " type string;\n"
1487 " }\n"
1488 " leaf g7 {\n"
1489 " type string;\n"
1490 " }\n"
1491 " }\n"
1492 " case y2 {\n"
1493 " leaf g8 {\n"
1494 " type string;\n"
1495 " }\n"
1496 " }\n"
1497 " }\n"
1498 " }\n"
1499 " }\n"
1500 " }\n"
1501 "}";
1502
1503 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
1504
1505 CHECK_PARSE_LYD_PARAM(
1506 "{\n"
1507 " \"k:ch\": {\n"
1508 " \"g0\": \"value_g0\",\n"
1509 " \"g7\": \"value_g7\"\n"
1510 " }\n"
1511 "}\n", LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
1512 CHECK_LOG_CTX("Data for both cases \"v0\" and \"v2\" exist.",
Michal Vasko09e04632023-03-22 14:34:10 +01001513 "Data location \"/k:ch\", line number 6.");
Michal Vasko8d151222021-07-22 12:12:41 +02001514
1515 CHECK_PARSE_LYD_PARAM(
1516 "{\n"
1517 " \"k:ch\": {\n"
1518 " \"g7\": \"value_g7\",\n"
1519 " \"g0\": \"value_g0\"\n"
1520 " }\n"
1521 "}\n", LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
1522 CHECK_LOG_CTX("Data for both cases \"v0\" and \"v2\" exist.",
Michal Vasko09e04632023-03-22 14:34:10 +01001523 "Data location \"/k:ch\", line number 6.");
Michal Vasko8d151222021-07-22 12:12:41 +02001524}
1525
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001526int
1527main(void)
Michal Vaskocde73ac2019-11-14 16:10:27 +01001528{
1529 const struct CMUnitTest tests[] = {
Radek Iša56ca9e42020-09-08 18:42:00 +02001530 UTEST(test_when),
1531 UTEST(test_mandatory),
Christian Hoppsb6ecaea2021-02-06 09:45:38 -05001532 UTEST(test_mandatory_when),
Michal Vasko850d8cb2022-08-05 12:51:00 +02001533 UTEST(test_type_incomplete_when),
Radek Iša56ca9e42020-09-08 18:42:00 +02001534 UTEST(test_minmax),
1535 UTEST(test_unique),
1536 UTEST(test_unique_nested),
1537 UTEST(test_dup),
1538 UTEST(test_defaults),
1539 UTEST(test_state),
1540 UTEST(test_must),
Michal Vaskod027f382023-02-10 09:13:25 +01001541 UTEST(test_multi_error),
Radek Iša56ca9e42020-09-08 18:42:00 +02001542 UTEST(test_action),
aPiecek18a844e2021-08-10 11:06:24 +02001543 UTEST(test_rpc),
Radek Iša56ca9e42020-09-08 18:42:00 +02001544 UTEST(test_reply),
Michal Vasko8d151222021-07-22 12:12:41 +02001545 UTEST(test_case),
Michal Vaskocde73ac2019-11-14 16:10:27 +01001546 };
1547
Radek Iša56ca9e42020-09-08 18:42:00 +02001548 return cmocka_run_group_tests(tests, NULL, NULL);
Michal Vaskocde73ac2019-11-14 16:10:27 +01001549}