blob: 9549d0376ee49fc0102e11f5450d9e8722ea6c8a [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"
25#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);
Radek Krejci2efc45b2020-12-22 16:25:44 +010060 CHECK_LOG_CTX("When condition \"/cont/b = 'val_b'\" not satisfied.", "Schema location /a:c, 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
76test_mandatory(void **state)
77{
78 struct lyd_node *tree;
79 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +010080 "module b {\n"
81 " namespace urn:tests:b;\n"
82 " prefix b;\n"
83 " yang-version 1.1;\n"
84 "\n"
85 " choice choic {\n"
86 " mandatory true;\n"
87 " leaf a {\n"
88 " type string;\n"
89 " }\n"
90 " case b {\n"
91 " leaf l {\n"
92 " type string;\n"
93 " }\n"
94 " }\n"
95 " }\n"
96 " leaf c {\n"
97 " mandatory true;\n"
98 " type string;\n"
99 " }\n"
100 " leaf d {\n"
101 " type empty;\n"
102 " }\n"
103 "}";
Radek Iša56ca9e42020-09-08 18:42:00 +0200104
105 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
106
107 CHECK_PARSE_LYD_PARAM("<d xmlns=\"urn:tests:b\"/>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100108 CHECK_LOG_CTX("Mandatory node \"choic\" instance does not exist.", "Schema location /b:choic.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200109
110 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);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100111 CHECK_LOG_CTX("Mandatory node \"c\" instance does not exist.", "Schema location /b:c.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200112
113 CHECK_PARSE_LYD_PARAM("<a xmlns=\"urn:tests:b\">string</a>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100114 CHECK_LOG_CTX("Mandatory node \"c\" instance does not exist.", "Schema location /b:c.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200115
116 LYD_TREE_CREATE("<a xmlns=\"urn:tests:b\">string</a><c xmlns=\"urn:tests:b\">string2</c>", tree);
117 lyd_free_siblings(tree);
118}
119
120static void
121test_minmax(void **state)
122{
123 struct lyd_node *tree;
124 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100125 "module c {\n"
126 " namespace urn:tests:c;\n"
127 " prefix c;\n"
128 " yang-version 1.1;\n"
129 "\n"
130 " choice choic {\n"
131 " leaf a {\n"
132 " type string;\n"
133 " }\n"
134 " case b {\n"
135 " leaf-list l {\n"
136 " min-elements 3;\n"
137 " type string;\n"
138 " }\n"
139 " }\n"
140 " }\n"
141 " list lt {\n"
142 " max-elements 4;\n"
143 " key \"k\";\n"
144 " leaf k {\n"
145 " type string;\n"
146 " }\n"
147 " }\n"
148 " leaf d {\n"
149 " type empty;\n"
150 " }\n"
151 "}";
Radek Iša56ca9e42020-09-08 18:42:00 +0200152
153 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
154
Michal Vasko6c16cda2021-02-04 11:05:52 +0100155 CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:c\">mate</l>"
156 "<d xmlns=\"urn:tests:c\"/>",
157 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100158 CHECK_LOG_CTX("Too few \"l\" instances.", "Schema location /c:choic/b/l.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200159
160 CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:c\">val1</l>"
161 "<l xmlns=\"urn:tests:c\">val2</l>",
162 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100163 CHECK_LOG_CTX("Too few \"l\" instances.", "Schema location /c:choic/b/l.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200164
165 LYD_TREE_CREATE("<l xmlns=\"urn:tests:c\">val1</l>"
166 "<l xmlns=\"urn:tests:c\">val2</l>"
167 "<l xmlns=\"urn:tests:c\">val3</l>", tree);
168 lyd_free_all(tree);
169
170 CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:c\">val1</l>"
171 "<l xmlns=\"urn:tests:c\">val2</l>"
172 "<l xmlns=\"urn:tests:c\">val3</l>"
173 "<lt xmlns=\"urn:tests:c\"><k>val1</k></lt>"
174 "<lt xmlns=\"urn:tests:c\"><k>val2</k></lt>"
175 "<lt xmlns=\"urn:tests:c\"><k>val3</k></lt>"
176 "<lt xmlns=\"urn:tests:c\"><k>val4</k></lt>"
Radek Krejci2efc45b2020-12-22 16:25:44 +0100177 "<lt xmlns=\"urn:tests:c\"><k>val5</k></lt>"
178 "<lt xmlns=\"urn:tests:c\"><k>val6</k></lt>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
179 CHECK_LOG_CTX("Too many \"lt\" instances.", "Schema location /c:lt, data location /c:lt[k='val5'].");
Radek Iša56ca9e42020-09-08 18:42:00 +0200180}
181
182const char *schema_d =
183 "module d {\n"
184 " namespace urn:tests:d;\n"
185 " prefix d;\n"
186 " yang-version 1.1;\n"
187 "\n"
188 " list lt {\n"
189 " key \"k\";\n"
190 " unique \"l1\";\n"
191 " leaf k {\n"
192 " type string;\n"
193 " }\n"
194 " leaf l1 {\n"
195 " type string;\n"
196 " }\n"
197 " }\n"
198 " list lt2 {\n"
199 " key \"k\";\n"
200 " unique \"cont/l2 l4\";\n"
201 " unique \"l5 l6\";\n"
202 " leaf k {\n"
203 " type string;\n"
204 " }\n"
205 " container cont {\n"
206 " leaf l2 {\n"
207 " type string;\n"
208 " }\n"
209 " }\n"
210 " leaf l4 {\n"
211 " type string;\n"
212 " }\n"
213 " leaf l5 {\n"
214 " type string;\n"
215 " }\n"
216 " leaf l6 {\n"
217 " type string;\n"
218 " }\n"
219 " list lt3 {\n"
220 " key \"kk\";\n"
221 " unique \"l3\";\n"
222 " leaf kk {\n"
223 " type string;\n"
224 " }\n"
225 " leaf l3 {\n"
226 " type string;\n"
227 " }\n"
228 " }\n"
229 " }\n"
230 "}";
231
232static void
233test_unique(void **state)
234{
235 struct lyd_node *tree;
236
237 UTEST_ADD_MODULE(schema_d, LYS_IN_YANG, NULL, NULL);
238
239 LYD_TREE_CREATE("<lt xmlns=\"urn:tests:d\">\n"
240 " <k>val1</k>\n"
241 " <l1>same</l1>\n"
242 "</lt>\n"
243 "<lt xmlns=\"urn:tests:d\">\n"
244 " <k>val2</k>\n"
245 "</lt>", tree);
246 lyd_free_all(tree);
247
248 LYD_TREE_CREATE("<lt xmlns=\"urn:tests:d\">\n"
249 " <k>val1</k>\n"
250 " <l1>same</l1>\n"
251 "</lt>\n"
252 "<lt xmlns=\"urn:tests:d\">\n"
253 " <k>val2</k>\n"
254 " <l1>not-same</l1>\n"
255 "</lt>", tree);
256 lyd_free_all(tree);
257
258 CHECK_PARSE_LYD_PARAM("<lt xmlns=\"urn:tests:d\">\n"
259 " <k>val1</k>\n"
260 " <l1>same</l1>\n"
261 "</lt>\n"
262 "<lt xmlns=\"urn:tests:d\">\n"
263 " <k>val2</k>\n"
264 " <l1>same</l1>\n"
265 "</lt>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100266 CHECK_LOG_CTX("Unique data leaf(s) \"l1\" not satisfied in \"/d:lt[k='val1']\" and \"/d:lt[k='val2']\".",
267 "Schema location /d:lt, data location /d:lt[k='val2'].");
Radek Iša56ca9e42020-09-08 18:42:00 +0200268
269 /* now try with more instances */
270 LYD_TREE_CREATE("<lt xmlns=\"urn:tests:d\">\n"
271 " <k>val1</k>\n"
272 " <l1>1</l1>\n"
273 "</lt>\n"
274 "<lt xmlns=\"urn:tests:d\">\n"
275 " <k>val2</k>\n"
276 " <l1>2</l1>\n"
277 "</lt>\n"
278 "<lt xmlns=\"urn:tests:d\">\n"
279 " <k>val3</k>\n"
280 " <l1>3</l1>\n"
281 "</lt>\n"
282 "<lt xmlns=\"urn:tests:d\">\n"
283 " <k>val4</k>\n"
284 " <l1>4</l1>\n"
285 "</lt>\n"
286 "<lt xmlns=\"urn:tests:d\">\n"
287 " <k>val5</k>\n"
288 " <l1>5</l1>\n"
289 "</lt>\n"
290 "<lt xmlns=\"urn:tests:d\">\n"
291 " <k>val6</k>\n"
292 " <l1>6</l1>\n"
293 "</lt>\n"
294 "<lt xmlns=\"urn:tests:d\">\n"
295 " <k>val7</k>\n"
296 " <l1>7</l1>\n"
297 "</lt>\n"
298 "<lt xmlns=\"urn:tests:d\">\n"
299 " <k>val8</k>\n"
300 " <l1>8</l1>\n"
301 "</lt>", tree);
302 lyd_free_all(tree);
303
304 LYD_TREE_CREATE("<lt xmlns=\"urn:tests:d\">\n"
305 " <k>val1</k>\n"
306 " <l1>1</l1>\n"
307 "</lt>\n"
308 "<lt xmlns=\"urn:tests:d\">\n"
309 " <k>val2</k>\n"
310 " <l1>2</l1>\n"
311 "</lt>\n"
312 "<lt xmlns=\"urn:tests:d\">\n"
313 " <k>val3</k>\n"
314 " <l1>3</l1>\n"
315 "</lt>\n"
316 "<lt xmlns=\"urn:tests:d\">\n"
317 " <k>val4</k>\n"
318 "</lt>\n"
319 "<lt xmlns=\"urn:tests:d\">\n"
320 " <k>val5</k>\n"
321 " <l1>5</l1>\n"
322 "</lt>\n"
323 "<lt xmlns=\"urn:tests:d\">\n"
324 " <k>val6</k>\n"
325 " <l1>6</l1>\n"
326 "</lt>\n"
327 "<lt xmlns=\"urn:tests:d\">\n"
328 " <k>val7</k>\n"
329 "</lt>\n"
330 "<lt xmlns=\"urn:tests:d\">\n"
331 " <k>val8</k>\n"
332 "</lt>", tree);
333 lyd_free_all(tree);
334
335 CHECK_PARSE_LYD_PARAM("<lt xmlns=\"urn:tests:d\">\n"
336 " <k>val1</k>\n"
337 " <l1>1</l1>\n"
338 "</lt>\n"
339 "<lt xmlns=\"urn:tests:d\">\n"
340 " <k>val2</k>\n"
341 " <l1>2</l1>\n"
342 "</lt>\n"
343 "<lt xmlns=\"urn:tests:d\">\n"
344 " <k>val3</k>\n"
345 "</lt>\n"
346 "<lt xmlns=\"urn:tests:d\">\n"
347 " <k>val4</k>\n"
348 " <l1>4</l1>\n"
349 "</lt>\n"
350 "<lt xmlns=\"urn:tests:d\">\n"
351 " <k>val5</k>\n"
352 "</lt>\n"
353 "<lt xmlns=\"urn:tests:d\">\n"
354 " <k>val6</k>\n"
355 "</lt>\n"
356 "<lt xmlns=\"urn:tests:d\">\n"
357 " <k>val7</k>\n"
358 " <l1>2</l1>\n"
359 "</lt>\n"
360 "<lt xmlns=\"urn:tests:d\">\n"
361 " <k>val8</k>\n"
362 " <l1>8</l1>\n"
363 "</lt>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100364 CHECK_LOG_CTX("Unique data leaf(s) \"l1\" not satisfied in \"/d:lt[k='val7']\" and \"/d:lt[k='val2']\".",
365 "Schema location /d:lt, data location /d:lt[k='val2'].");
Radek Iša56ca9e42020-09-08 18:42:00 +0200366}
367
368static void
369test_unique_nested(void **state)
370{
371 struct lyd_node *tree;
372
373 UTEST_ADD_MODULE(schema_d, LYS_IN_YANG, NULL, NULL);
374
375 /* nested list uniquest are compared only with instances in the same parent list instance */
376 LYD_TREE_CREATE("<lt2 xmlns=\"urn:tests:d\">\n"
377 " <k>val1</k>\n"
378 " <cont>\n"
379 " <l2>1</l2>\n"
380 " </cont>\n"
381 " <l4>1</l4>\n"
382 "</lt2>\n"
383 "<lt2 xmlns=\"urn:tests:d\">\n"
384 " <k>val2</k>\n"
385 " <cont>\n"
386 " <l2>2</l2>\n"
387 " </cont>\n"
388 " <l4>2</l4>\n"
389 " <lt3>\n"
390 " <kk>val1</kk>\n"
391 " <l3>1</l3>\n"
392 " </lt3>\n"
393 " <lt3>\n"
394 " <kk>val2</kk>\n"
395 " <l3>2</l3>\n"
396 " </lt3>\n"
397 "</lt2>\n"
398 "<lt2 xmlns=\"urn:tests:d\">\n"
399 " <k>val3</k>\n"
400 " <cont>\n"
401 " <l2>3</l2>\n"
402 " </cont>\n"
403 " <l4>3</l4>\n"
404 " <lt3>\n"
405 " <kk>val1</kk>\n"
406 " <l3>2</l3>\n"
407 " </lt3>\n"
408 "</lt2>\n"
409 "<lt2 xmlns=\"urn:tests:d\">\n"
410 " <k>val4</k>\n"
411 " <cont>\n"
412 " <l2>4</l2>\n"
413 " </cont>\n"
414 " <l4>4</l4>\n"
415 " <lt3>\n"
416 " <kk>val1</kk>\n"
417 " <l3>3</l3>\n"
418 " </lt3>\n"
419 "</lt2>\n"
420 "<lt2 xmlns=\"urn:tests:d\">\n"
421 " <k>val5</k>\n"
422 " <cont>\n"
423 " <l2>5</l2>\n"
424 " </cont>\n"
425 " <l4>5</l4>\n"
426 " <lt3>\n"
427 " <kk>val1</kk>\n"
428 " <l3>3</l3>\n"
429 " </lt3>\n"
430 "</lt2>", tree);
431 lyd_free_all(tree);
432
433 CHECK_PARSE_LYD_PARAM("<lt2 xmlns=\"urn:tests:d\">\n"
434 " <k>val1</k>\n"
435 " <cont>\n"
436 " <l2>1</l2>\n"
437 " </cont>\n"
438 " <l4>1</l4>\n"
439 "</lt2>\n"
440 "<lt2 xmlns=\"urn:tests:d\">\n"
441 " <k>val2</k>\n"
442 " <cont>\n"
443 " <l2>2</l2>\n"
444 " </cont>\n"
445 " <lt3>\n"
446 " <kk>val1</kk>\n"
447 " <l3>1</l3>\n"
448 " </lt3>\n"
449 " <lt3>\n"
450 " <kk>val2</kk>\n"
451 " <l3>2</l3>\n"
452 " </lt3>\n"
453 " <lt3>\n"
454 " <kk>val3</kk>\n"
455 " <l3>1</l3>\n"
456 " </lt3>\n"
457 "</lt2>\n"
458 "<lt2 xmlns=\"urn:tests:d\">\n"
459 " <k>val3</k>\n"
460 " <cont>\n"
461 " <l2>3</l2>\n"
462 " </cont>\n"
463 " <l4>1</l4>\n"
464 " <lt3>\n"
465 " <kk>val1</kk>\n"
466 " <l3>2</l3>\n"
467 " </lt3>\n"
468 "</lt2>\n"
469 "<lt2 xmlns=\"urn:tests:d\">\n"
470 " <k>val4</k>\n"
471 " <cont>\n"
472 " <l2>4</l2>\n"
473 " </cont>\n"
474 " <lt3>\n"
475 " <kk>val1</kk>\n"
476 " <l3>3</l3>\n"
477 " </lt3>\n"
478 "</lt2>\n"
479 "<lt2 xmlns=\"urn:tests:d\">\n"
480 " <k>val5</k>\n"
481 " <cont>\n"
482 " <l2>5</l2>\n"
483 " </cont>\n"
484 " <lt3>\n"
485 " <kk>val1</kk>\n"
486 " <l3>3</l3>\n"
487 " </lt3>\n"
488 "</lt2>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100489 CHECK_LOG_CTX("Unique data leaf(s) \"l3\" not satisfied in \"/d:lt2[k='val2']/lt3[kk='val3']\" and \"/d:lt2[k='val2']/lt3[kk='val1']\".",
490 "Schema location /d:lt2/lt3, data location /d:lt2[k='val2']/lt3[kk='val1'].");
Radek Iša56ca9e42020-09-08 18:42:00 +0200491
492 CHECK_PARSE_LYD_PARAM("<lt2 xmlns=\"urn:tests:d\">\n"
493 " <k>val1</k>\n"
494 " <cont>\n"
495 " <l2>1</l2>\n"
496 " </cont>\n"
497 " <l4>1</l4>\n"
498 "</lt2>\n"
499 "<lt2 xmlns=\"urn:tests:d\">\n"
500 " <k>val2</k>\n"
501 " <cont>\n"
502 " <l2>2</l2>\n"
503 " </cont>\n"
504 " <l4>2</l4>\n"
505 "</lt2>\n"
506 "<lt2 xmlns=\"urn:tests:d\">\n"
507 " <k>val3</k>\n"
508 " <cont>\n"
509 " <l2>3</l2>\n"
510 " </cont>\n"
511 " <l4>3</l4>\n"
512 "</lt2>\n"
513 "<lt2 xmlns=\"urn:tests:d\">\n"
514 " <k>val4</k>\n"
515 " <cont>\n"
516 " <l2>2</l2>\n"
517 " </cont>\n"
518 " <l4>2</l4>\n"
519 "</lt2>\n"
520 "<lt2 xmlns=\"urn:tests:d\">\n"
521 " <k>val5</k>\n"
522 " <cont>\n"
523 " <l2>5</l2>\n"
524 " </cont>\n"
525 " <l4>5</l4>\n"
526 "</lt2>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100527 CHECK_LOG_CTX("Unique data leaf(s) \"cont/l2 l4\" not satisfied in \"/d:lt2[k='val4']\" and \"/d:lt2[k='val2']\".",
528 "Schema location /d:lt2, data location /d:lt2[k='val2'].");
Radek Iša56ca9e42020-09-08 18:42:00 +0200529
530 CHECK_PARSE_LYD_PARAM("<lt2 xmlns=\"urn:tests:d\">\n"
531 " <k>val1</k>\n"
532 " <cont>\n"
533 " <l2>1</l2>\n"
534 " </cont>\n"
535 " <l4>1</l4>\n"
536 " <l5>1</l5>\n"
537 " <l6>1</l6>\n"
538 "</lt2>\n"
539 "<lt2 xmlns=\"urn:tests:d\">\n"
540 " <k>val2</k>\n"
541 " <cont>\n"
542 " <l2>2</l2>\n"
543 " </cont>\n"
544 " <l4>1</l4>\n"
545 " <l5>1</l5>\n"
546 "</lt2>\n"
547 "<lt2 xmlns=\"urn:tests:d\">\n"
548 " <k>val3</k>\n"
549 " <cont>\n"
550 " <l2>3</l2>\n"
551 " </cont>\n"
552 " <l4>1</l4>\n"
553 " <l5>3</l5>\n"
554 " <l6>3</l6>\n"
555 "</lt2>\n"
556 "<lt2 xmlns=\"urn:tests:d\">\n"
557 " <k>val4</k>\n"
558 " <cont>\n"
559 " <l2>4</l2>\n"
560 " </cont>\n"
561 " <l4>1</l4>\n"
562 " <l6>1</l6>\n"
563 "</lt2>\n"
564 "<lt2 xmlns=\"urn:tests:d\">\n"
565 " <k>val5</k>\n"
566 " <cont>\n"
567 " <l2>5</l2>\n"
568 " </cont>\n"
569 " <l4>1</l4>\n"
570 " <l5>3</l5>\n"
571 " <l6>3</l6>\n"
572 "</lt2>", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
573 CHECK_LOG_CTX("Unique data leaf(s) \"l5 l6\" not satisfied in \"/d:lt2[k='val5']\" and \"/d:lt2[k='val3']\".",
Radek Krejci2efc45b2020-12-22 16:25:44 +0100574 "Schema location /d:lt2, data location /d:lt2[k='val3'].");
Radek Iša56ca9e42020-09-08 18:42:00 +0200575}
576
577static void
578test_dup(void **state)
579{
580 struct lyd_node *tree;
581 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100582 "module e {\n"
583 " namespace urn:tests:e;\n"
584 " prefix e;\n"
585 " yang-version 1.1;\n"
586 "\n"
587 " choice choic {\n"
588 " leaf a {\n"
589 " type string;\n"
590 " }\n"
591 " case b {\n"
592 " leaf-list l {\n"
593 " type string;\n"
594 " }\n"
595 " }\n"
596 " }\n"
597 " list lt {\n"
598 " key \"k\";\n"
599 " leaf k {\n"
600 " type string;\n"
601 " }\n"
602 " }\n"
603 " leaf d {\n"
604 " type uint32;\n"
605 " }\n"
606 " leaf-list ll {\n"
607 " type string;\n"
608 " }\n"
609 " container cont {\n"
610 " list lt {\n"
611 " key \"k\";\n"
612 " leaf k {\n"
613 " type string;\n"
614 " }\n"
615 " }\n"
616 " leaf d {\n"
617 " type uint32;\n"
618 " }\n"
619 " leaf-list ll {\n"
620 " type string;\n"
621 " }\n"
622 " leaf-list ll2 {\n"
623 " type enumeration {\n"
624 " enum one;\n"
625 " enum two;\n"
626 " }\n"
627 " }\n"
628 " }\n"
629 "}";
Radek Iša56ca9e42020-09-08 18:42:00 +0200630
631 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
632
633 CHECK_PARSE_LYD_PARAM("<d xmlns=\"urn:tests:e\">25</d><d xmlns=\"urn:tests:e\">50</d>",
634 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100635 CHECK_LOG_CTX("Duplicate instance of \"d\".", "Schema location /e:d, data location /e:d.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200636
637 CHECK_PARSE_LYD_PARAM("<lt xmlns=\"urn:tests:e\"><k>A</k></lt>"
638 "<lt xmlns=\"urn:tests:e\"><k>B</k></lt>"
639 "<lt xmlns=\"urn:tests:e\"><k>A</k></lt>",
640 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100641 CHECK_LOG_CTX("Duplicate instance of \"lt\".", "Schema location /e:lt, data location /e:lt[k='A'].");
Radek Iša56ca9e42020-09-08 18:42:00 +0200642
643 CHECK_PARSE_LYD_PARAM("<ll xmlns=\"urn:tests:e\">A</ll>"
644 "<ll xmlns=\"urn:tests:e\">B</ll>"
645 "<ll xmlns=\"urn:tests:e\">B</ll>",
646 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100647 CHECK_LOG_CTX("Duplicate instance of \"ll\".", "Schema location /e:ll, data location /e:ll[.='B'].");
Radek Iša56ca9e42020-09-08 18:42:00 +0200648
649 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:e\"></cont><cont xmlns=\"urn:tests:e\"/>",
650 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100651 CHECK_LOG_CTX("Duplicate instance of \"cont\".", "Schema location /e:cont, data location /e:cont.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200652
653 /* same tests again but using hashes */
654 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>",
655 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100656 CHECK_LOG_CTX("Duplicate instance of \"d\".", "Schema location /e:cont/d, data location /e:cont/d, line number 1.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200657
658 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:e\"><ll>1</ll><ll>2</ll><ll>3</ll><ll>4</ll>"
659 "<lt><k>a</k></lt>"
660 "<lt><k>b</k></lt>"
661 "<lt><k>c</k></lt>"
662 "<lt><k>d</k></lt>"
663 "<lt><k>c</k></lt></cont>",
664 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100665 CHECK_LOG_CTX("Duplicate instance of \"lt\".", "Schema location /e:cont/lt, data location /e:cont/lt[k='c'], line number 1.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200666
667 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:e\"><ll>1</ll><ll>2</ll><ll>3</ll><ll>4</ll>"
668 "<ll>a</ll><ll>b</ll><ll>c</ll><ll>d</ll><ll>d</ll></cont>",
669 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100670 CHECK_LOG_CTX("Duplicate instance of \"ll\".", "Schema location /e:cont/ll, data location /e:cont/ll[.='d'], line number 1.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200671
672 /* cases */
673 CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:e\">a</l>"
674 "<l xmlns=\"urn:tests:e\">b</l>"
675 "<l xmlns=\"urn:tests:e\">c</l>"
676 "<l xmlns=\"urn:tests:e\">b</l>",
677 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100678 CHECK_LOG_CTX("Duplicate instance of \"l\".", "Schema location /e:choic/b/l, data location /e:l[.='b'].");
Radek Iša56ca9e42020-09-08 18:42:00 +0200679
680 CHECK_PARSE_LYD_PARAM("<l xmlns=\"urn:tests:e\">a</l><l xmlns=\"urn:tests:e\">b</l>"
681 "<l xmlns=\"urn:tests:e\">c</l>"
682 "<a xmlns=\"urn:tests:e\">aa</a>",
683 LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100684 CHECK_LOG_CTX("Data for both cases \"a\" and \"b\" exist.", "Schema location /e:choic.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200685}
686
687static void
688test_defaults(void **state)
689{
690 struct lyd_node *tree, *node, *diff;
691 const struct lys_module *mod;
692 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100693 "module f {\n"
694 " namespace urn:tests:f;\n"
695 " prefix f;\n"
696 " yang-version 1.1;\n"
697 "\n"
698 " choice choic {\n"
699 " default \"c\";\n"
700 " leaf a {\n"
701 " type string;\n"
702 " }\n"
703 " case b {\n"
704 " leaf l {\n"
705 " type string;\n"
706 " }\n"
707 " }\n"
708 " case c {\n"
709 " leaf-list ll1 {\n"
710 " type string;\n"
711 " default \"def1\";\n"
712 " default \"def2\";\n"
713 " default \"def3\";\n"
714 " }\n"
715 " }\n"
716 " }\n"
717 " leaf d {\n"
718 " type uint32;\n"
719 " default 15;\n"
720 " }\n"
721 " leaf-list ll2 {\n"
722 " type string;\n"
723 " default \"dflt1\";\n"
724 " default \"dflt2\";\n"
725 " }\n"
726 " container cont {\n"
727 " choice choic {\n"
728 " default \"c\";\n"
729 " leaf a {\n"
730 " type string;\n"
731 " }\n"
732 " case b {\n"
733 " leaf l {\n"
734 " type string;\n"
735 " }\n"
736 " }\n"
737 " case c {\n"
738 " leaf-list ll1 {\n"
739 " type string;\n"
740 " default \"def1\";\n"
741 " default \"def2\";\n"
742 " default \"def3\";\n"
743 " }\n"
744 " }\n"
745 " }\n"
746 " leaf d {\n"
747 " type uint32;\n"
748 " default 15;\n"
749 " }\n"
750 " leaf-list ll2 {\n"
751 " type string;\n"
752 " default \"dflt1\";\n"
753 " default \"dflt2\";\n"
754 " }\n"
755 " }\n"
756 "}";
Radek Iša56ca9e42020-09-08 18:42:00 +0200757
758 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod);
759
760 assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
761 assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf-with-defaults", "2011-06-01", NULL));\
762
763 /* get defaults */
764 tree = NULL;
765 assert_int_equal(lyd_validate_module(&tree, mod, 0, &diff), LY_SUCCESS);
766 assert_non_null(tree);
767 assert_non_null(diff);
768
769 /* check all defaults exist */
770 CHECK_LYD_STRING_PARAM(tree,
771 "<ll1 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>\n"
772 "<ll1 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>\n"
773 "<ll1 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def3</ll1>\n"
774 "<d xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
775 "<ll2 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
776 "<ll2 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
777 "<cont xmlns=\"urn:tests:f\">\n"
778 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>\n"
779 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>\n"
780 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def3</ll1>\n"
781 " <d xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
782 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
783 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
784 "</cont>\n",
785 LYD_XML, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_WITHSIBLINGS);
786
787 /* check diff */
788 CHECK_LYD_STRING_PARAM(diff,
789 "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">def1</ll1>\n"
790 "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">def2</ll1>\n"
791 "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">def3</ll1>\n"
792 "<d xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">15</d>\n"
793 "<ll2 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">dflt1</ll2>\n"
794 "<ll2 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">dflt2</ll2>\n"
795 "<cont xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"create\">\n"
796 " <ll1 yang:operation=\"create\">def1</ll1>\n"
797 " <ll1 yang:operation=\"create\">def2</ll1>\n"
798 " <ll1 yang:operation=\"create\">def3</ll1>\n"
799 " <d yang:operation=\"create\">15</d>\n"
800 " <ll2 yang:operation=\"create\">dflt1</ll2>\n"
801 " <ll2 yang:operation=\"create\">dflt2</ll2>\n"
802 "</cont>\n",
803 LYD_XML, LYD_PRINT_WD_ALL | LYD_PRINT_WITHSIBLINGS);
804 lyd_free_all(diff);
805
806 /* create another explicit case and validate */
807 assert_int_equal(lyd_new_term(NULL, mod, "l", "value", 0, &node), LY_SUCCESS);
808 assert_int_equal(lyd_insert_sibling(tree, node, &tree), LY_SUCCESS);
809 assert_int_equal(lyd_validate_all(&tree, UTEST_LYCTX, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
810
811 /* check data tree */
812 CHECK_LYD_STRING_PARAM(tree,
813 "<l xmlns=\"urn:tests:f\">value</l>\n"
814 "<d xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
815 "<ll2 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
816 "<ll2 xmlns=\"urn:tests:f\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
817 "<cont xmlns=\"urn:tests:f\">\n"
818 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>\n"
819 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>\n"
820 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def3</ll1>\n"
821 " <d xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
822 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
823 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
824 "</cont>\n",
825 LYD_XML, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_WITHSIBLINGS);
826
827 /* check diff */
828 CHECK_LYD_STRING_PARAM(diff,
829 "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">def1</ll1>\n"
830 "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">def2</ll1>\n"
831 "<ll1 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">def3</ll1>\n",
832 LYD_XML, LYD_PRINT_WD_ALL | LYD_PRINT_WITHSIBLINGS);
833 lyd_free_all(diff);
834
835 /* create explicit leaf-list and leaf and validate */
836 assert_int_equal(lyd_new_term(NULL, mod, "d", "15", 0, &node), LY_SUCCESS);
837 assert_int_equal(lyd_insert_sibling(tree, node, &tree), LY_SUCCESS);
838 assert_int_equal(lyd_new_term(NULL, mod, "ll2", "dflt2", 0, &node), LY_SUCCESS);
839 assert_int_equal(lyd_insert_sibling(tree, node, &tree), LY_SUCCESS);
840 assert_int_equal(lyd_validate_all(&tree, UTEST_LYCTX, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
841
842 /* check data tree */
843 CHECK_LYD_STRING_PARAM(tree,
844 "<l xmlns=\"urn:tests:f\">value</l>\n"
845 "<d xmlns=\"urn:tests:f\">15</d>\n"
846 "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>\n"
847 "<cont xmlns=\"urn:tests:f\">\n"
848 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>\n"
849 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>\n"
850 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def3</ll1>\n"
851 " <d xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
852 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
853 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
854 "</cont>\n",
855 LYD_XML, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_WITHSIBLINGS);
856
857 /* check diff */
858 CHECK_LYD_STRING_PARAM(diff,
859 "<d xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">15</d>\n"
860 "<ll2 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">dflt1</ll2>\n"
861 "<ll2 xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"delete\">dflt2</ll2>\n",
862 LYD_XML, LYD_PRINT_WD_ALL | LYD_PRINT_WITHSIBLINGS);
863 lyd_free_all(diff);
864
865 /* create first explicit container, which should become implicit */
866 assert_int_equal(lyd_new_inner(NULL, mod, "cont", 0, &node), LY_SUCCESS);
867 assert_int_equal(lyd_insert_sibling(tree, node, &tree), LY_SUCCESS);
868 assert_int_equal(lyd_validate_all(&tree, UTEST_LYCTX, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
869
870 /* check data tree */
871 CHECK_LYD_STRING_PARAM(tree,
872 "<l xmlns=\"urn:tests:f\">value</l>\n"
873 "<d xmlns=\"urn:tests:f\">15</d>\n"
874 "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>\n"
875 "<cont xmlns=\"urn:tests:f\">\n"
876 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>\n"
877 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>\n"
878 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def3</ll1>\n"
879 " <d xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
880 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
881 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
882 "</cont>\n",
883 LYD_XML, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_WITHSIBLINGS);
884 /* check diff */
885 assert_null(diff);
886
887 /* create second explicit container, which should become implicit, so the first tree node should be removed */
888 assert_int_equal(lyd_new_inner(NULL, mod, "cont", 0, &node), LY_SUCCESS);
889 assert_int_equal(lyd_insert_sibling(tree, node, &tree), LY_SUCCESS);
890 assert_int_equal(lyd_validate_all(&tree, UTEST_LYCTX, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
891
892 /* check data tree */
893 CHECK_LYD_STRING_PARAM(tree,
894 "<l xmlns=\"urn:tests:f\">value</l>\n"
895 "<d xmlns=\"urn:tests:f\">15</d>\n"
896 "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>\n"
897 "<cont xmlns=\"urn:tests:f\">\n"
898 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def1</ll1>\n"
899 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def2</ll1>\n"
900 " <ll1 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">def3</ll1>\n"
901 " <d xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">15</d>\n"
902 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt1</ll2>\n"
903 " <ll2 xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" ncwd:default=\"true\">dflt2</ll2>\n"
904 "</cont>\n",
905 LYD_XML, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_WITHSIBLINGS);
906 /* check diff */
907 assert_null(diff);
908
909 /* similar changes for nested defaults */
910 assert_int_equal(lyd_new_term(tree->prev, NULL, "ll1", "def3", 0, NULL), LY_SUCCESS);
911 assert_int_equal(lyd_new_term(tree->prev, NULL, "d", "5", 0, NULL), LY_SUCCESS);
912 assert_int_equal(lyd_new_term(tree->prev, NULL, "ll2", "non-dflt", 0, NULL), LY_SUCCESS);
913 assert_int_equal(lyd_validate_all(&tree, UTEST_LYCTX, LYD_VALIDATE_PRESENT, &diff), LY_SUCCESS);
914
915 /* check data tree */
916 CHECK_LYD_STRING_PARAM(tree,
917 "<l xmlns=\"urn:tests:f\">value</l>\n"
918 "<d xmlns=\"urn:tests:f\">15</d>\n"
919 "<ll2 xmlns=\"urn:tests:f\">dflt2</ll2>\n"
920 "<cont xmlns=\"urn:tests:f\">\n"
921 " <ll1>def3</ll1>\n"
922 " <d>5</d>\n"
923 " <ll2>non-dflt</ll2>\n"
924 "</cont>\n",
925 LYD_XML, LYD_PRINT_WITHSIBLINGS);
926
927 /* check diff */
928 CHECK_LYD_STRING_PARAM(diff,
929 "<cont xmlns=\"urn:tests:f\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
930 " <ll1 yang:operation=\"delete\">def1</ll1>\n"
931 " <ll1 yang:operation=\"delete\">def2</ll1>\n"
932 " <ll1 yang:operation=\"delete\">def3</ll1>\n"
933 " <d yang:operation=\"delete\">15</d>\n"
934 " <ll2 yang:operation=\"delete\">dflt1</ll2>\n"
935 " <ll2 yang:operation=\"delete\">dflt2</ll2>\n"
936 "</cont>\n",
937 LYD_XML, LYD_PRINT_WD_ALL | LYD_PRINT_WITHSIBLINGS);
938 lyd_free_all(diff);
939 lyd_free_all(tree);
940}
941
942static void
943test_state(void **state)
944{
945 const char *data;
946 struct lyd_node *tree;
947 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100948 "module h {\n"
949 " namespace urn:tests:h;\n"
950 " prefix h;\n"
951 " yang-version 1.1;\n"
952 "\n"
953 " container cont {\n"
954 " container cont2 {\n"
955 " config false;\n"
956 " leaf l {\n"
957 " type string;\n"
958 " }\n"
959 " }\n"
960 " }\n"
961 "}";
Radek Iša56ca9e42020-09-08 18:42:00 +0200962
963 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
964
965 data = "<cont xmlns=\"urn:tests:h\">\n"
966 " <cont2>\n"
967 " <l>val</l>\n"
968 " </cont2>\n"
969 "</cont>\n";
970 CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_NO_STATE, 0, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +0100971 CHECK_LOG_CTX("Invalid state data node \"cont2\" found.",
972 "Schema location /h:cont/cont2, data location /h:cont, line number 3.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200973
974 CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
975 assert_int_equal(LY_EVALID, lyd_validate_all(&tree, NULL, LYD_VALIDATE_PRESENT | LYD_VALIDATE_NO_STATE, NULL));
Radek Krejci2efc45b2020-12-22 16:25:44 +0100976 CHECK_LOG_CTX("Invalid state data node \"cont2\" found.",
977 "Schema location /h:cont/cont2, data location /h:cont/cont2.");
Radek Iša56ca9e42020-09-08 18:42:00 +0200978 lyd_free_all(tree);
979}
980
981static void
982test_must(void **state)
983{
984 struct lyd_node *tree;
985 const char *schema =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100986 "module i {\n"
987 " namespace urn:tests:i;\n"
988 " prefix i;\n"
989 " yang-version 1.1;\n"
990 "\n"
991 " container cont {\n"
992 " leaf l {\n"
993 " type string;\n"
994 " }\n"
995 " leaf l2 {\n"
996 " must \"../l = 'right'\";\n"
997 " type string;\n"
998 " }\n"
999 " }\n"
1000 "}";
Michal Vaskocde73ac2019-11-14 16:10:27 +01001001
Radek Iša56ca9e42020-09-08 18:42:00 +02001002 UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
Michal Vaskocde73ac2019-11-14 16:10:27 +01001003
Radek Iša56ca9e42020-09-08 18:42:00 +02001004 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:i\">\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001005 " <l>wrong</l>\n"
1006 " <l2>val</l2>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001007 "</cont>\n", LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
Radek Krejci2efc45b2020-12-22 16:25:44 +01001008 CHECK_LOG_CTX("Must condition \"../l = 'right'\" not satisfied.",
1009 "Schema location /i:cont/l2, data location /i:cont/l2.");
Michal Vaskocc048b22020-03-27 15:52:38 +01001010
Radek Iša56ca9e42020-09-08 18:42:00 +02001011 LYD_TREE_CREATE("<cont xmlns=\"urn:tests:i\">\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001012 " <l>right</l>\n"
1013 " <l2>val</l2>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001014 "</cont>\n", tree);
1015 lyd_free_all(tree);
Michal Vaskocc048b22020-03-27 15:52:38 +01001016}
1017
Radek Iša56ca9e42020-09-08 18:42:00 +02001018const char *schema_j =
1019 "module j {\n"
1020 " namespace urn:tests:j;\n"
1021 " prefix j;\n"
1022 " yang-version 1.1;\n"
1023 "\n"
1024 " feature feat1;\n"
1025 "\n"
1026 " container cont {\n"
1027 " must \"false()\";\n"
1028 " list l1 {\n"
1029 " key \"k\";\n"
1030 " leaf k {\n"
1031 " type string;\n"
1032 " }\n"
1033 " action act {\n"
1034 " if-feature feat1;\n"
1035 " input {\n"
1036 " must \"../../lf1 = 'true'\";\n"
1037 " leaf lf2 {\n"
1038 " type leafref {\n"
1039 " path /lf3;\n"
1040 " }\n"
1041 " }\n"
1042 " }\n"
1043 " output {\n"
1044 " must \"../../lf1 = 'true2'\";\n"
1045 " leaf lf2 {\n"
1046 " type leafref {\n"
1047 " path /lf4;\n"
1048 " }\n"
1049 " }\n"
1050 " }\n"
1051 " }\n"
1052 " }\n"
1053 "\n"
1054 " leaf lf1 {\n"
1055 " type string;\n"
1056 " }\n"
1057 " }\n"
1058 "\n"
1059 " leaf lf3 {\n"
1060 " type string;\n"
1061 " }\n"
1062 "\n"
1063 " leaf lf4 {\n"
1064 " type string;\n"
1065 " }\n"
1066 "}";
1067const char *feats_j[] = {"feat1", NULL};
1068
Michal Vaskofea12c62020-03-30 11:00:15 +02001069static void
1070test_action(void **state)
1071{
Michal Vasko63f3d842020-07-08 10:10:14 +02001072 struct ly_in *in;
Michal Vaskofea12c62020-03-30 11:00:15 +02001073 struct lyd_node *tree, *op_tree;
Michal Vaskofea12c62020-03-30 11:00:15 +02001074
Radek Iša56ca9e42020-09-08 18:42:00 +02001075 UTEST_ADD_MODULE(schema_j, LYS_IN_YANG, feats_j, NULL);
1076
1077 assert_int_equal(LY_SUCCESS, ly_in_new_memory(
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001078 "<cont xmlns=\"urn:tests:j\">\n"
1079 " <l1>\n"
1080 " <k>val1</k>\n"
1081 " <act>\n"
1082 " <lf2>target</lf2>\n"
1083 " </act>\n"
1084 " </l1>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001085 "</cont>\n", &in));
1086 assert_int_equal(LY_SUCCESS, lyd_parse_rpc(UTEST_LYCTX, in, LYD_XML, &op_tree, NULL));
Michal Vaskofea12c62020-03-30 11:00:15 +02001087 assert_non_null(op_tree);
1088
1089 /* missing leafref */
Michal Vasko8104fd42020-07-13 11:09:51 +02001090 assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_VALIDATE_OP_RPC, NULL));
Radek Krejci2efc45b2020-12-22 16:25:44 +01001091 CHECK_LOG_CTX("Invalid leafref value \"target\" - no existing target instance \"/lf3\".",
Radek Krejci2a9fc652021-01-22 17:44:34 +01001092 "Schema location /j:cont/l1/act/input/lf2, data location /j:cont/l1[k='val1']/act/lf2.");
Michal Vasko63f3d842020-07-08 10:10:14 +02001093 ly_in_free(in, 0);
Michal Vaskofea12c62020-03-30 11:00:15 +02001094
Radek Iša56ca9e42020-09-08 18:42:00 +02001095 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:j\">\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001096 " <lf1>not true</lf1>\n"
1097 "</cont>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001098 "<lf3 xmlns=\"urn:tests:j\">target</lf3>\n",
1099 LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
Michal Vaskofea12c62020-03-30 11:00:15 +02001100
Michal Vaskofea12c62020-03-30 11:00:15 +02001101 /* input must false */
Michal Vasko8104fd42020-07-13 11:09:51 +02001102 assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_RPC, NULL));
Radek Krejci2efc45b2020-12-22 16:25:44 +01001103 CHECK_LOG_CTX("Must condition \"../../lf1 = 'true'\" not satisfied.",
1104 "Data location /j:cont/l1[k='val1']/act.");
Michal Vaskofea12c62020-03-30 11:00:15 +02001105
Radek Iša56ca9e42020-09-08 18:42:00 +02001106 lyd_free_all(tree);
1107 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:j\">\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001108 " <lf1>true</lf1>\n"
1109 "</cont>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001110 "<lf3 xmlns=\"urn:tests:j\">target</lf3>\n",
1111 LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
Michal Vaskofea12c62020-03-30 11:00:15 +02001112
1113 /* success */
Michal Vasko8104fd42020-07-13 11:09:51 +02001114 assert_int_equal(LY_SUCCESS, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_RPC, NULL));
Michal Vaskofea12c62020-03-30 11:00:15 +02001115
Michal Vaskocb7526d2020-03-30 15:08:26 +02001116 lyd_free_tree(op_tree);
1117 lyd_free_siblings(tree);
Michal Vaskocb7526d2020-03-30 15:08:26 +02001118}
1119
1120static void
1121test_reply(void **state)
1122{
Michal Vasko63f3d842020-07-08 10:10:14 +02001123 struct ly_in *in;
Michal Vasko2552ea32020-12-08 15:32:34 +01001124 struct lyd_node *tree, *op_tree;
Michal Vaskocb7526d2020-03-30 15:08:26 +02001125
Radek Iša56ca9e42020-09-08 18:42:00 +02001126 UTEST_ADD_MODULE(schema_j, LYS_IN_YANG, feats_j, NULL);
1127
1128 assert_int_equal(LY_SUCCESS, ly_in_new_memory(
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001129 "<cont xmlns=\"urn:tests:j\">\n"
1130 " <l1>\n"
1131 " <k>val1</k>\n"
1132 " <act>\n"
1133 " <lf2>target</lf2>\n"
1134 " </act>\n"
1135 " </l1>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001136 "</cont>\n", &in));
Michal Vasko2552ea32020-12-08 15:32:34 +01001137 assert_int_equal(LY_SUCCESS, lyd_parse_reply(UTEST_LYCTX, in, LYD_XML, &op_tree, NULL));
Michal Vaskocb7526d2020-03-30 15:08:26 +02001138 assert_non_null(op_tree);
Michal Vasko63f3d842020-07-08 10:10:14 +02001139 ly_in_free(in, 0);
Michal Vaskocb7526d2020-03-30 15:08:26 +02001140
1141 /* missing leafref */
Michal Vasko8104fd42020-07-13 11:09:51 +02001142 assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, NULL, LYD_VALIDATE_OP_REPLY, NULL));
Radek Krejci2efc45b2020-12-22 16:25:44 +01001143 CHECK_LOG_CTX("Invalid leafref value \"target\" - no existing target instance \"/lf4\".",
Radek Krejci2a9fc652021-01-22 17:44:34 +01001144 "Schema location /j:cont/l1/act/output/lf2, data location /j:cont/l1[k='val1']/act/lf2.");
Michal Vaskocb7526d2020-03-30 15:08:26 +02001145
Radek Iša56ca9e42020-09-08 18:42:00 +02001146 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:j\">\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001147 " <lf1>not true</lf1>\n"
1148 "</cont>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001149 "<lf4 xmlns=\"urn:tests:j\">target</lf4>\n",
1150 LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
Michal Vaskocb7526d2020-03-30 15:08:26 +02001151
Michal Vaskocb7526d2020-03-30 15:08:26 +02001152 /* input must false */
Michal Vasko8104fd42020-07-13 11:09:51 +02001153 assert_int_equal(LY_EVALID, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_REPLY, NULL));
Radek Krejci2efc45b2020-12-22 16:25:44 +01001154 CHECK_LOG_CTX("Must condition \"../../lf1 = 'true2'\" not satisfied.", "Data location /j:cont/l1[k='val1']/act.");
Michal Vaskocb7526d2020-03-30 15:08:26 +02001155
Radek Iša56ca9e42020-09-08 18:42:00 +02001156 lyd_free_all(tree);
1157 CHECK_PARSE_LYD_PARAM("<cont xmlns=\"urn:tests:j\">\n"
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001158 " <lf1>true2</lf1>\n"
1159 "</cont>\n"
Radek Iša56ca9e42020-09-08 18:42:00 +02001160 "<lf4 xmlns=\"urn:tests:j\">target</lf4>\n",
1161 LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree);
Michal Vaskocb7526d2020-03-30 15:08:26 +02001162
1163 /* success */
Michal Vasko8104fd42020-07-13 11:09:51 +02001164 assert_int_equal(LY_SUCCESS, lyd_validate_op(op_tree, tree, LYD_VALIDATE_OP_REPLY, NULL));
Michal Vaskocb7526d2020-03-30 15:08:26 +02001165
Michal Vaskofea12c62020-03-30 11:00:15 +02001166 lyd_free_tree(op_tree);
Radek Iša56ca9e42020-09-08 18:42:00 +02001167 lyd_free_all(tree);
Michal Vaskofea12c62020-03-30 11:00:15 +02001168}
1169
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001170int
1171main(void)
Michal Vaskocde73ac2019-11-14 16:10:27 +01001172{
1173 const struct CMUnitTest tests[] = {
Radek Iša56ca9e42020-09-08 18:42:00 +02001174 UTEST(test_when),
1175 UTEST(test_mandatory),
1176 UTEST(test_minmax),
1177 UTEST(test_unique),
1178 UTEST(test_unique_nested),
1179 UTEST(test_dup),
1180 UTEST(test_defaults),
1181 UTEST(test_state),
1182 UTEST(test_must),
1183 UTEST(test_action),
1184 UTEST(test_reply),
Michal Vaskocde73ac2019-11-14 16:10:27 +01001185 };
1186
Radek Iša56ca9e42020-09-08 18:42:00 +02001187 return cmocka_run_group_tests(tests, NULL, NULL);
Michal Vaskocde73ac2019-11-14 16:10:27 +01001188}