blob: 1e919b10a4dcec7d19e218a0176efe886f4feed5 [file] [log] [blame]
Michal Vasko93923692021-05-07 15:28:02 +02001/**
Michal Vasko14795a42020-05-22 16:44:44 +02002 * @file test_xpath.c
3 * @author: Michal Vasko <mvasko@cesnet.cz>
4 * @brief unit tests for XPath evaluation
5 *
6 * Copyright (c) 2020 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
Radek Iša56ca9e42020-09-08 18:42:00 +020014#define _UTEST_MAIN_
15#include "utests.h"
Michal Vasko14795a42020-05-22 16:44:44 +020016
Michal Vasko14795a42020-05-22 16:44:44 +020017#include <string.h>
18
Radek Krejci70593c12020-06-13 20:48:09 +020019#include "context.h"
Radek Krejci7931b192020-06-25 17:05:03 +020020#include "parser_data.h"
Radek Krejci70593c12020-06-13 20:48:09 +020021#include "set.h"
Radek Krejcief5f7672021-04-01 17:04:12 +020022#include "tests_config.h"
Radek Krejci70593c12020-06-13 20:48:09 +020023#include "tree_data.h"
24#include "tree_schema.h"
Michal Vasko14795a42020-05-22 16:44:44 +020025
Radek Iša56ca9e42020-09-08 18:42:00 +020026const char *schema_a =
27 "module a {\n"
28 " namespace urn:tests:a;\n"
29 " prefix a;\n"
30 " yang-version 1.1;\n"
31 "\n"
Michal Vasko93923692021-05-07 15:28:02 +020032 " identity id_a;\n"
33 " identity id_b {\n"
34 " base id_a;\n"
35 " }\n"
36 " identity id_c {\n"
37 " base id_b;\n"
38 " }\n"
39 "\n"
Radek Iša56ca9e42020-09-08 18:42:00 +020040 " list l1 {\n"
41 " key \"a b\";\n"
42 " leaf a {\n"
43 " type string;\n"
44 " }\n"
45 " leaf b {\n"
46 " type string;\n"
47 " }\n"
48 " leaf c {\n"
49 " type string;\n"
50 " }\n"
51 " }\n"
52 " leaf foo {\n"
53 " type string;\n"
54 " }\n"
55 " leaf foo2 {\n"
56 " type uint8;\n"
57 " }\n"
Michal Vasko93923692021-05-07 15:28:02 +020058 " leaf foo3 {\n"
59 " type identityref {\n"
60 " base id_a;\n"
61 " }\n"
62 " }\n"
Michal Vasko00099082022-07-28 10:07:41 +020063 " leaf foo4 {\n"
64 " type decimal64 {\n"
65 " fraction-digits 5;\n"
66 " }\n"
67 " }\n"
Radek Iša56ca9e42020-09-08 18:42:00 +020068 " container c {\n"
69 " leaf x {\n"
70 " type string;\n"
71 " }\n"
72 " list ll {\n"
73 " key \"a\";\n"
74 " leaf a {\n"
75 " type string;\n"
76 " }\n"
77 " list ll {\n"
78 " key \"a\";\n"
79 " leaf a {\n"
80 " type string;\n"
81 " }\n"
82 " leaf b {\n"
83 " type string;\n"
84 " }\n"
85 " }\n"
86 " }\n"
87 " leaf-list ll2 {\n"
88 " type string;\n"
89 " }\n"
90 " }\n"
91 "}";
Michal Vasko14795a42020-05-22 16:44:44 +020092
93static int
94setup(void **state)
95{
Radek Iša56ca9e42020-09-08 18:42:00 +020096 UTEST_SETUP;
Michal Vasko14795a42020-05-22 16:44:44 +020097
Radek Iša56ca9e42020-09-08 18:42:00 +020098 UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, NULL, NULL);
Michal Vasko14795a42020-05-22 16:44:44 +020099
100 return 0;
101}
102
Michal Vasko14795a42020-05-22 16:44:44 +0200103static void
aPiecekfff4dca2021-10-07 10:59:53 +0200104test_predicate(void **state)
105{
106 const char *data;
107 struct lyd_node *tree;
108 struct ly_set *set;
109
110 data =
Michal Vasko49fec8e2022-05-24 10:28:33 +0200111 "<foo2 xmlns=\"urn:tests:a\">50</foo2>"
112 "<c xmlns=\"urn:tests:a\">"
113 " <x>val</x>"
114 " <ll>"
115 " <a>key1</a>"
116 " <ll>"
117 " <a>key11</a>"
118 " <b>val11</b>"
119 " </ll>"
120 " <ll>"
121 " <a>key12</a>"
122 " <b>val12</b>"
123 " </ll>"
124 " <ll>"
125 " <a>key13</a>"
126 " <b>val13</b>"
127 " </ll>"
128 " </ll>"
129 " <ll>"
130 " <a>key2</a>"
131 " <ll>"
132 " <a>key21</a>"
133 " <b>val21</b>"
134 " </ll>"
135 " <ll>"
136 " <a>key22</a>"
137 " <b>val22</b>"
138 " </ll>"
139 " </ll>"
140 "</c>";
aPiecekfff4dca2021-10-07 10:59:53 +0200141 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
142 assert_non_null(tree);
143
Michal Vasko49fec8e2022-05-24 10:28:33 +0200144 /* predicate after number */
aPiecekfff4dca2021-10-07 10:59:53 +0200145 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/foo2[4[3 = 3]]", &set));
Michal Vasko49fec8e2022-05-24 10:28:33 +0200146 assert_int_equal(0, set->count);
147 ly_set_free(set, NULL);
148
149 /* reverse axis */
150 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/child::ll[2]/preceding::ll[3]", &set));
151 assert_int_equal(1, set->count);
152 assert_string_equal("key11", lyd_get_value(lyd_child(set->dnodes[0])));
aPiecekfff4dca2021-10-07 10:59:53 +0200153 ly_set_free(set, NULL);
154
155 lyd_free_all(tree);
156}
157
158static void
aPiecekadc1e4f2021-10-07 11:15:12 +0200159test_union(void **state)
160{
161 const char *data;
162 struct lyd_node *tree;
163 struct ly_set *set;
164
165 data =
166 "<l1 xmlns=\"urn:tests:a\">\n"
167 " <a>a1</a>\n"
168 " <b>b1</b>\n"
169 " <c>c1</c>\n"
170 "</l1>\n"
171 "<l1 xmlns=\"urn:tests:a\">\n"
172 " <a>a2</a>\n"
173 " <b>b2</b>\n"
174 "</l1>"
175 "<l1 xmlns=\"urn:tests:a\">\n"
176 " <a>a3</a>\n"
177 " <b>b3</b>\n"
178 " <c>c3</c>\n"
179 "</l1>";
180 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
181 assert_non_null(tree);
182
183 /* Predicate for operand. */
184 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/l1[c[../a = 'a1'] | c]/a", &set));
185 ly_set_free(set, NULL);
186
187 lyd_free_all(tree);
188}
189
190static void
Michal Vaskoe2be5462021-08-04 10:49:42 +0200191test_invalid(void **state)
192{
193 const char *data =
194 "<foo2 xmlns=\"urn:tests:a\">50</foo2>";
195 struct lyd_node *tree;
196 struct ly_set *set;
197
198 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
199 assert_non_null(tree);
200
201 assert_int_equal(LY_EVALID, lyd_find_xpath(tree, "/a:foo2[.=]", &set));
202 assert_null(set);
203
204 assert_int_equal(LY_EVALID, lyd_find_xpath(tree, "/a:", &set));
205 assert_null(set);
206
207 lyd_free_all(tree);
208}
209
210static void
Michal Vasko14795a42020-05-22 16:44:44 +0200211test_hash(void **state)
212{
Michal Vasko14795a42020-05-22 16:44:44 +0200213 const char *data =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100214 "<l1 xmlns=\"urn:tests:a\">\n"
215 " <a>a1</a>\n"
216 " <b>b1</b>\n"
217 " <c>c1</c>\n"
218 "</l1>\n"
219 "<l1 xmlns=\"urn:tests:a\">\n"
220 " <a>a2</a>\n"
221 " <b>b2</b>\n"
222 "</l1>\n"
223 "<l1 xmlns=\"urn:tests:a\">\n"
224 " <a>a3</a>\n"
225 " <b>b3</b>\n"
226 " <c>c3</c>\n"
227 "</l1>\n"
228 "<foo xmlns=\"urn:tests:a\">foo value</foo>\n"
229 "<c xmlns=\"urn:tests:a\">\n"
230 " <x>val</x>\n"
231 " <ll>\n"
232 " <a>val_a</a>\n"
233 " <ll>\n"
234 " <a>val_a</a>\n"
235 " <b>val</b>\n"
236 " </ll>\n"
237 " <ll>\n"
238 " <a>val_b</a>\n"
239 " </ll>\n"
240 " </ll>\n"
241 " <ll>\n"
242 " <a>val_b</a>\n"
243 " <ll>\n"
244 " <a>val_a</a>\n"
245 " </ll>\n"
246 " <ll>\n"
247 " <a>val_b</a>\n"
248 " <b>val</b>\n"
249 " </ll>\n"
250 " </ll>\n"
251 " <ll>\n"
252 " <a>val_c</a>\n"
253 " <ll>\n"
254 " <a>val_a</a>\n"
255 " </ll>\n"
256 " <ll>\n"
257 " <a>val_b</a>\n"
258 " </ll>\n"
259 " </ll>\n"
260 " <ll2>one</ll2>\n"
261 " <ll2>two</ll2>\n"
262 " <ll2>three</ll2>\n"
263 " <ll2>four</ll2>\n"
264 "</c>";
Michal Vasko14795a42020-05-22 16:44:44 +0200265 struct lyd_node *tree, *node;
266 struct ly_set *set;
Michal Vasko14795a42020-05-22 16:44:44 +0200267
Radek Iša56ca9e42020-09-08 18:42:00 +0200268 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
Michal Vasko14795a42020-05-22 16:44:44 +0200269 assert_non_null(tree);
270
271 /* top-level, so hash table is not ultimately used but instances can be compared based on hashes */
272 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:l1[a='a3'][b='b3']", &set));
273 assert_int_equal(1, set->count);
274
275 node = set->objs[0];
276 assert_string_equal(node->schema->name, "l1");
Radek Krejcia1c1e542020-09-29 16:06:52 +0200277 node = lyd_child(node);
Michal Vasko14795a42020-05-22 16:44:44 +0200278 assert_string_equal(node->schema->name, "a");
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200279 assert_string_equal(lyd_get_value(node), "a3");
Michal Vasko14795a42020-05-22 16:44:44 +0200280
281 ly_set_free(set, NULL);
282
283 /* hashes should be used for both searches (well, there are not enough nested ll instances, so technically not true) */
284 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[a='val_b']/ll[a='val_b']", &set));
285 assert_int_equal(1, set->count);
286
287 node = set->objs[0];
288 assert_string_equal(node->schema->name, "ll");
Radek Krejcia1c1e542020-09-29 16:06:52 +0200289 node = lyd_child(node);
Michal Vasko14795a42020-05-22 16:44:44 +0200290 assert_string_equal(node->schema->name, "a");
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200291 assert_string_equal(lyd_get_value(node), "val_b");
Michal Vasko14795a42020-05-22 16:44:44 +0200292 node = node->next;
293 assert_string_equal(node->schema->name, "b");
294 assert_null(node->next);
295
296 ly_set_free(set, NULL);
297
298 /* hashes are not used */
299 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c//ll[a='val_b']", &set));
300 assert_int_equal(4, set->count);
301
302 ly_set_free(set, NULL);
303
Michal Vasko660cc8f2020-05-25 10:33:19 +0200304 /* hashes used even for leaf-lists */
305 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll2[. = 'three']", &set));
306 assert_int_equal(1, set->count);
307
308 node = set->objs[0];
309 assert_string_equal(node->schema->name, "ll2");
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200310 assert_string_equal(lyd_get_value(node), "three");
Michal Vasko660cc8f2020-05-25 10:33:19 +0200311
312 ly_set_free(set, NULL);
313
Michal Vasko14795a42020-05-22 16:44:44 +0200314 /* not found using hashes */
315 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[a='val_d']", &set));
316 assert_int_equal(0, set->count);
317
318 ly_set_free(set, NULL);
319
320 /* white-spaces are also ok */
321 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[ \na = 'val_c' ]", &set));
322 assert_int_equal(1, set->count);
323
324 ly_set_free(set, NULL);
325
326 lyd_free_all(tree);
Michal Vasko14795a42020-05-22 16:44:44 +0200327}
328
Michal Vasko61ac2f62020-05-25 12:39:51 +0200329static void
330test_toplevel(void **state)
331{
Radek Iša56ca9e42020-09-08 18:42:00 +0200332 const char *schema_b =
333 "module b {\n"
334 " namespace urn:tests:b;\n"
335 " prefix b;\n"
336 " yang-version 1.1;\n"
337 "\n"
338 " list l2 {\n"
339 " key \"a\";\n"
340 " leaf a {\n"
341 " type uint16;\n"
342 " }\n"
343 " leaf b {\n"
344 " type uint16;\n"
345 " }\n"
346 " }\n"
347 "}";
Michal Vasko61ac2f62020-05-25 12:39:51 +0200348 const char *data =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100349 "<l1 xmlns=\"urn:tests:a\">\n"
350 " <a>a1</a>\n"
351 " <b>b1</b>\n"
352 " <c>c1</c>\n"
353 "</l1>\n"
354 "<l1 xmlns=\"urn:tests:a\">\n"
355 " <a>a2</a>\n"
356 " <b>b2</b>\n"
357 "</l1>\n"
358 "<l1 xmlns=\"urn:tests:a\">\n"
359 " <a>a3</a>\n"
360 " <b>b3</b>\n"
361 " <c>c3</c>\n"
362 "</l1>\n"
363 "<foo xmlns=\"urn:tests:a\">foo value</foo>\n"
364 "<l2 xmlns=\"urn:tests:b\">\n"
365 " <a>1</a>\n"
366 " <b>1</b>\n"
367 "</l2>\n"
368 "<l2 xmlns=\"urn:tests:b\">\n"
369 " <a>2</a>\n"
370 " <b>1</b>\n"
371 "</l2>\n"
372 "<l2 xmlns=\"urn:tests:b\">\n"
373 " <a>3</a>\n"
374 " <b>1</b>\n"
375 "</l2>";
Michal Vaskof60e7102020-05-26 10:48:59 +0200376 struct lyd_node *tree;
Michal Vasko61ac2f62020-05-25 12:39:51 +0200377 struct ly_set *set;
Michal Vasko61ac2f62020-05-25 12:39:51 +0200378
Radek Iša56ca9e42020-09-08 18:42:00 +0200379 UTEST_ADD_MODULE(schema_b, LYS_IN_YANG, NULL, NULL);
380
381 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
Michal Vasko61ac2f62020-05-25 12:39:51 +0200382 assert_non_null(tree);
383
384 /* all top-level nodes from one module (default container as well) */
385 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:*", &set));
386 assert_int_equal(5, set->count);
387
388 ly_set_free(set, NULL);
389
390 /* all top-level nodes from all modules */
391 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/*", &set));
392 assert_int_equal(8, set->count);
393
394 ly_set_free(set, NULL);
395
396 /* all nodes from one module */
397 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//a:*", &set));
398 assert_int_equal(13, set->count);
399
400 ly_set_free(set, NULL);
401
402 /* all nodes from all modules */
403 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//*", &set));
404 assert_int_equal(22, set->count);
405
406 ly_set_free(set, NULL);
407
408 /* all nodes from all modules #2 */
409 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//.", &set));
410 assert_int_equal(22, set->count);
411
412 ly_set_free(set, NULL);
413
414 lyd_free_all(tree);
Michal Vasko61ac2f62020-05-25 12:39:51 +0200415}
416
Michal Vasko519fd602020-05-26 12:17:39 +0200417static void
418test_atomize(void **state)
419{
Michal Vasko519fd602020-05-26 12:17:39 +0200420 struct ly_set *set;
421 const struct lys_module *mod;
422
Radek Iša56ca9e42020-09-08 18:42:00 +0200423 mod = ly_ctx_get_module_latest(UTEST_LYCTX, "a");
424 assert_non_null(mod);
Michal Vasko519fd602020-05-26 12:17:39 +0200425
426 /* some random paths just making sure the API function works */
Michal Vasko400e9672021-01-11 13:39:17 +0100427 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:*", 0, &set));
Michal Vasko00099082022-07-28 10:07:41 +0200428 assert_int_equal(6, set->count);
Michal Vasko519fd602020-05-26 12:17:39 +0200429 ly_set_free(set, NULL);
430
431 /* all nodes from all modules (including internal, which can change easily, so check just the test modules) */
Michal Vasko400e9672021-01-11 13:39:17 +0100432 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "//.", 0, &set));
Michal Vasko93923692021-05-07 15:28:02 +0200433 assert_in_range(set->count, 17, UINT32_MAX);
Michal Vasko519fd602020-05-26 12:17:39 +0200434 ly_set_free(set, NULL);
435
Michal Vasko400e9672021-01-11 13:39:17 +0100436 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:c/ll[a='val1']/ll[a='val2']/b", 0, &set));
437 assert_int_equal(6, set->count);
Michal Vasko49fec8e2022-05-24 10:28:33 +0200438 ly_set_free(set, NULL);
Michal Vasko519fd602020-05-26 12:17:39 +0200439
Michal Vasko49fec8e2022-05-24 10:28:33 +0200440 /*
441 * axes
442 */
443
444 /* ancestor */
445 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "//ll[a and b]/a/ancestor::node()", 0, &set));
446 assert_int_equal(6, set->count);
447 ly_set_free(set, NULL);
448
449 /* ancestor-or-self */
450 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "//ll[a and b]/ancestor-or-self::ll", 0, &set));
451 assert_int_equal(5, set->count);
452 ly_set_free(set, NULL);
453
454 /* attribute */
455 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/l1/attribute::key", 0, &set));
456 assert_int_equal(1, set->count);
457 ly_set_free(set, NULL);
458
459 /* child */
460 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/child::l1/child::a", 0, &set));
461 assert_int_equal(2, set->count);
462 ly_set_free(set, NULL);
463
464 /* descendant */
465 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/descendant::c/descendant::b", 0, &set));
466 assert_int_equal(3, set->count);
467 ly_set_free(set, NULL);
468
469 /* descendant-or-self */
470 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:*/descendant-or-self::c", 0, &set));
Michal Vasko00099082022-07-28 10:07:41 +0200471 assert_int_equal(7, set->count);
Michal Vasko49fec8e2022-05-24 10:28:33 +0200472 ly_set_free(set, NULL);
473
474 /* following */
475 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/x/following::a", 0, &set));
476 assert_int_equal(4, set->count);
477 ly_set_free(set, NULL);
478
479 /* following-sibling */
480 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/x/following-sibling::ll", 0, &set));
481 assert_int_equal(3, set->count);
482 ly_set_free(set, NULL);
483
484 /* parent */
485 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/child::a:*/c/parent::l1", 0, &set));
Michal Vasko00099082022-07-28 10:07:41 +0200486 assert_int_equal(7, set->count);
Michal Vasko49fec8e2022-05-24 10:28:33 +0200487 ly_set_free(set, NULL);
488
489 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/child::a:c//..", 0, &set));
490 assert_int_equal(8, set->count);
491 ly_set_free(set, NULL);
492
493 /* preceding */
494 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/preceding::a", 0, &set));
495 assert_int_equal(2, set->count);
496 ly_set_free(set, NULL);
497
498 /* preceding-sibling */
499 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/ll/preceding-sibling::node()", 0, &set));
500 assert_int_equal(3, set->count);
501 ly_set_free(set, NULL);
502
503 /* self */
504 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/self::c/ll/ll/b/self::b", 0, &set));
505 assert_int_equal(4, set->count);
Michal Vasko519fd602020-05-26 12:17:39 +0200506 ly_set_free(set, NULL);
507}
508
Michal Vasko4c7763f2020-07-27 17:40:37 +0200509static void
510test_canonize(void **state)
511{
Michal Vasko4c7763f2020-07-27 17:40:37 +0200512 const char *data =
Michal Vasko00099082022-07-28 10:07:41 +0200513 "<foo2 xmlns=\"urn:tests:a\">50</foo2>"
514 "<foo3 xmlns=\"urn:tests:a\" xmlns:a=\"urn:tests:a\">a:id_b</foo3>"
515 "<foo4 xmlns=\"urn:tests:a\">250.5</foo4>";
Michal Vasko4c7763f2020-07-27 17:40:37 +0200516 struct lyd_node *tree;
517 struct ly_set *set;
518
Radek Iša56ca9e42020-09-08 18:42:00 +0200519 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
Michal Vasko4c7763f2020-07-27 17:40:37 +0200520 assert_non_null(tree);
521
Michal Vasko00099082022-07-28 10:07:41 +0200522 /* integer */
Michal Vasko4c7763f2020-07-27 17:40:37 +0200523 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo2[.='050']", &set));
524 assert_int_equal(1, set->count);
525 ly_set_free(set, NULL);
526
Michal Vasko00099082022-07-28 10:07:41 +0200527 /* identityref */
528 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo3[.='id_b']", &set));
529 assert_int_equal(1, set->count);
530 ly_set_free(set, NULL);
531
532 /* decimal64 */
533 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo4[.='0250.500']", &set));
534 assert_int_equal(1, set->count);
535 ly_set_free(set, NULL);
Michal Vasko4c7763f2020-07-27 17:40:37 +0200536
537 lyd_free_all(tree);
Michal Vasko4c7763f2020-07-27 17:40:37 +0200538}
539
Michal Vasko93923692021-05-07 15:28:02 +0200540static void
541test_derived_from(void **state)
542{
543 const char *data =
544 "<foo3 xmlns=\"urn:tests:a\">id_c</foo3>";
545 struct lyd_node *tree;
546 struct ly_set *set;
547
548 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
549 assert_non_null(tree);
550
551 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo3[derived-from(., 'a:id_b')]", &set));
552 assert_int_equal(1, set->count);
553 ly_set_free(set, NULL);
554
555 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo3[derived-from(., 'a:id_a')]", &set));
556 assert_int_equal(1, set->count);
557 ly_set_free(set, NULL);
558
559 lyd_free_all(tree);
560}
561
Michal Vaskodb08ce52021-10-06 08:57:49 +0200562static void
563test_augment(void **state)
564{
565 const char *schema_b =
566 "module b {\n"
567 " namespace urn:tests:b;\n"
568 " prefix b;\n"
569 " yang-version 1.1;\n"
570 "\n"
571 " import a {\n"
572 " prefix a;\n"
573 " }\n"
574 "\n"
575 " augment /a:c {\n"
576 " leaf a {\n"
577 " type uint16;\n"
578 " }\n"
579 " }\n"
580 "}";
581 const char *data =
582 "<c xmlns=\"urn:tests:a\">\n"
583 " <x>value</x>\n"
584 " <ll>\n"
585 " <a>key</a>\n"
586 " </ll>\n"
587 " <a xmlns=\"urn:tests:b\">25</a>\n"
588 " <ll2>c1</ll2>\n"
589 "</c>";
590 struct lyd_node *tree;
591 struct ly_set *set;
592
593 UTEST_ADD_MODULE(schema_b, LYS_IN_YANG, NULL, NULL);
594
595 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
596 assert_non_null(tree);
597
598 /* get all children ignoring their module */
599 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/*", &set));
600 assert_int_equal(4, set->count);
601
602 ly_set_free(set, NULL);
603
604 lyd_free_all(tree);
605}
606
aPiecekfba75362021-10-07 12:39:48 +0200607static void
608test_variables(void **state)
609{
610 struct lyd_node *tree, *node;
611 struct ly_set *set;
612 const char *data;
613 struct lyxp_var *vars = NULL;
614
615#define LOCAL_SETUP(DATA, TREE) \
616 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, DATA, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &TREE)); \
617 assert_non_null(TREE);
618
619#define SET_NODE(NODE, SET, INDEX) \
620 assert_non_null(SET); \
621 assert_true(INDEX < SET->count); \
622 NODE = SET->objs[INDEX];
623
624#define LOCAL_TEARDOWN(SET, TREE, VARS) \
625 ly_set_free(SET, NULL); \
626 lyd_free_all(TREE); \
627 lyxp_vars_free(VARS); \
628 vars = NULL;
629
630 /* Eval variable to number. */
631 data =
632 "<l1 xmlns=\"urn:tests:a\">\n"
633 " <a>a1</a>\n"
634 " <b>b1</b>\n"
635 " <c>c1</c>\n"
636 "</l1>"
637 "<l1 xmlns=\"urn:tests:a\">\n"
638 " <a>a2</a>\n"
639 " <b>b2</b>\n"
640 " <c>c2</c>\n"
641 "</l1>";
642 LOCAL_SETUP(data, tree);
643 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "2"));
644 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var]/a", vars, &set));
645 SET_NODE(node, set, 0);
646 assert_string_equal(lyd_get_value(node), "a2");
647 LOCAL_TEARDOWN(set, tree, vars);
648
649 /* Eval variable to string. */
650 data =
651 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
652 LOCAL_SETUP(data, tree);
653 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "\"mstr\""));
654 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/foo[text() = $var]", vars, &set));
655 SET_NODE(node, set, 0);
656 assert_string_equal(lyd_get_value(node), "mstr");
657 LOCAL_TEARDOWN(set, tree, vars);
658
659 /* Eval variable to set of nodes. */
660 data =
661 "<l1 xmlns=\"urn:tests:a\">\n"
662 " <a>a1</a>\n"
663 " <b>b1</b>\n"
664 "</l1>"
665 "<l1 xmlns=\"urn:tests:a\">\n"
666 " <a>a2</a>\n"
667 " <b>b2</b>\n"
668 " <c>c2</c>\n"
669 "</l1>";
670 LOCAL_SETUP(data, tree);
671 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "c"));
672 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var]/a", vars, &set));
673 SET_NODE(node, set, 0);
674 assert_string_equal(lyd_get_value(node), "a2");
675 LOCAL_TEARDOWN(set, tree, vars);
676
677 /* Variable in union expr. */
678 data =
679 "<l1 xmlns=\"urn:tests:a\">\n"
680 " <a>a1</a>\n"
681 " <b>b1</b>\n"
682 " <c>c1</c>\n"
683 "</l1>"
684 "<l1 xmlns=\"urn:tests:a\">\n"
685 " <a>a2</a>\n"
686 " <b>b2</b>\n"
687 " <c>c2</c>\n"
688 "</l1>"
689 "<l1 xmlns=\"urn:tests:a\">\n"
690 " <a>a3</a>\n"
691 " <b>b3</b>\n"
692 " <c>c3</c>\n"
693 "</l1>";
694 LOCAL_SETUP(data, tree);
695 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "c[../a = 'a3']"));
696 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[c[../a = 'a1'] | $var]/a", vars, &set));
697 SET_NODE(node, set, 0);
698 assert_string_equal(lyd_get_value(node), "a1");
699 SET_NODE(node, set, 1);
700 assert_string_equal(lyd_get_value(node), "a3");
701 assert_int_equal(set->count, 2);
702 LOCAL_TEARDOWN(set, tree, vars);
703
704 /* Predicate after variable. */
705 data =
706 "<l1 xmlns=\"urn:tests:a\">\n"
707 " <a>a1</a>\n"
708 " <b>b1</b>\n"
709 " <c>c1</c>\n"
710 "</l1>"
711 "<l1 xmlns=\"urn:tests:a\">\n"
712 " <a>a2</a>\n"
713 " <b>b2</b>\n"
714 " <c>c2</c>\n"
715 "</l1>";
716 LOCAL_SETUP(data, tree);
717 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "c"));
718 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var[../a = 'a1']]/a", vars, &set));
719 SET_NODE(node, set, 0);
720 assert_string_equal(lyd_get_value(node), "a1");
721 LOCAL_TEARDOWN(set, tree, vars);
722
723 /* Variable in variable. */
724 data =
725 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
726 LOCAL_SETUP(data, tree);
727 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "$var2"));
728 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var2", "\"mstr\""));
729 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/foo[text() = $var]", vars, &set));
730 SET_NODE(node, set, 0);
731 assert_string_equal(lyd_get_value(node), "mstr");
732 LOCAL_TEARDOWN(set, tree, vars);
733
734 /* Compare two variables. */
735 data =
736 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
737 LOCAL_SETUP(data, tree);
738 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "\"str\""));
739 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var2", "\"str\""));
740 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/foo[$var1 = $var2]", vars, &set));
741 SET_NODE(node, set, 0);
742 assert_string_equal(lyd_get_value(node), "mstr");
743 LOCAL_TEARDOWN(set, tree, vars);
744
745 /* Arithmetic operation with variable. */
746 data =
747 "<foo2 xmlns=\"urn:tests:a\">4</foo2>";
748 LOCAL_SETUP(data, tree);
749 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "2"));
750 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/foo2[.= ($var1 * 2)]", vars, &set));
751 SET_NODE(node, set, 0);
752 assert_string_equal(lyd_get_value(node), "4");
753 LOCAL_TEARDOWN(set, tree, vars);
754
755 /* Variable as function parameter. */
756 data =
757 "<l1 xmlns=\"urn:tests:a\">\n"
758 " <a>a1</a>\n"
759 " <b>b1</b>\n"
760 " <c>c1</c>\n"
761 "</l1>"
762 "<l1 xmlns=\"urn:tests:a\">\n"
763 " <a>a2</a>\n"
764 " <b>b2</b>\n"
765 "</l1>";
766 LOCAL_SETUP(data, tree);
767 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "./c"));
768 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[count($var) = 1]/a", vars, &set));
769 SET_NODE(node, set, 0);
770 assert_string_equal(lyd_get_value(node), "a1");
771 LOCAL_TEARDOWN(set, tree, vars);
772
773 /* Variable in path expr. */
774 /* NOTE: The variable can only be at the beginning of the expression path. */
775 data =
776 "<l1 xmlns=\"urn:tests:a\">\n"
777 " <a>a1</a>\n"
778 " <b>b1</b>\n"
779 " <c>c1</c>\n"
780 "</l1>"
781 "<l1 xmlns=\"urn:tests:a\">\n"
782 " <a>a2</a>\n"
783 " <b>b2</b>\n"
784 "</l1>";
785 LOCAL_SETUP(data, tree);
786 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "/l1"));
787 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var/a]", vars, &set));
788 assert_int_equal(set->count, 2);
789 LOCAL_TEARDOWN(set, tree, vars);
790
791 /* Variable as function. */
792 data =
793 "<l1 xmlns=\"urn:tests:a\">\n"
794 " <a>a1</a>\n"
795 " <b>b1</b>\n"
796 " <c>c1</c>\n"
797 "</l1>"
798 "<l1 xmlns=\"urn:tests:a\">\n"
799 " <a>a2</a>\n"
800 " <b>b2</b>\n"
801 "</l1>";
802 LOCAL_SETUP(data, tree);
803 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "position()"));
804 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var = 2]/a", vars, &set));
805 SET_NODE(node, set, 0);
806 assert_string_equal(lyd_get_value(node), "a2");
807 LOCAL_TEARDOWN(set, tree, vars);
808
809 /* Dynamic change of value. */
810 data =
811 "<l1 xmlns=\"urn:tests:a\">\n"
812 " <a>a1</a>\n"
813 " <b>b1</b>\n"
814 " <c>c1</c>\n"
815 "</l1>"
816 "<l1 xmlns=\"urn:tests:a\">\n"
817 " <a>a2</a>\n"
818 " <b>b2</b>\n"
819 " <c>c2</c>\n"
820 "</l1>";
821 LOCAL_SETUP(data, tree);
822 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "1"));
823 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var]/a", vars, &set));
824 SET_NODE(node, set, 0);
825 assert_string_equal(lyd_get_value(node), "a1");
826 ly_set_free(set, NULL);
827 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "2"));
828 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var]/a", vars, &set));
829 SET_NODE(node, set, 0);
830 assert_string_equal(lyd_get_value(node), "a2");
831 LOCAL_TEARDOWN(set, tree, vars);
832
833 /* Variable not defined. */
834 data =
835 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
836 LOCAL_SETUP(data, tree);
837 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "\"mstr\""));
838 assert_int_equal(LY_ENOTFOUND, lyd_find_xpath2(tree, "/foo[text() = $var55]", vars, &set));
839 LOCAL_TEARDOWN(set, tree, vars);
840
841 /* Syntax error in value. */
842 data =
843 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
844 LOCAL_SETUP(data, tree);
845 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "\""));
846 assert_int_equal(LY_EVALID, lyd_find_xpath2(tree, "/foo[$var]", vars, &set));
847 LOCAL_TEARDOWN(set, tree, vars);
848
849 /* Prefix is not supported. */
850 data =
851 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
852 LOCAL_SETUP(data, tree);
853 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "\""));
854 assert_int_equal(LY_EVALID, lyd_find_xpath2(tree, "/foo[$pref:var]", vars, &set));
855 assert_string_equal("Variable with prefix is not supported.", _UC->err_msg);
856 LOCAL_TEARDOWN(set, tree, vars);
857
858#undef LOCAL_SETUP
859#undef LOCAL_TEARDOWN
860}
861
Michal Vasko49fec8e2022-05-24 10:28:33 +0200862static void
863test_axes(void **state)
864{
865 const char *data;
866 struct lyd_node *tree;
867 struct ly_set *set;
868
869 data =
870 "<l1 xmlns=\"urn:tests:a\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\">\n"
871 " <a>a1</a>\n"
872 " <b yang:operation=\"replace\">b1</b>\n"
873 " <c yang:operation=\"none\">c1</c>\n"
874 "</l1>\n"
875 "<l1 xmlns=\"urn:tests:a\">\n"
876 " <a>a2</a>\n"
877 " <b>b2</b>\n"
878 "</l1>"
879 "<l1 xmlns=\"urn:tests:a\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\">\n"
Michal Vasko79a7a872022-06-17 09:00:48 +0200880 " <a yang:operation=\"none\" yang:key=\"[no-key='no-value']\">a3</a>\n"
Michal Vasko49fec8e2022-05-24 10:28:33 +0200881 " <b>b3</b>\n"
882 " <c yang:value=\"no-val\">c3</c>\n"
883 "</l1>"
884 "<c xmlns=\"urn:tests:a\">"
885 " <x>val</x>"
886 " <ll>"
887 " <a>key1</a>"
888 " <ll>"
889 " <a>key11</a>"
890 " <b>val11</b>"
891 " </ll>"
892 " <ll>"
893 " <a>key12</a>"
894 " <b>val12</b>"
895 " </ll>"
896 " <ll>"
897 " <a>key13</a>"
898 " <b>val13</b>"
899 " </ll>"
900 " </ll>"
901 " <ll>"
902 " <a>key2</a>"
903 " <ll>"
904 " <a>key21</a>"
905 " <b>val21</b>"
906 " </ll>"
907 " <ll>"
908 " <a>key22</a>"
909 " <b>val22</b>"
910 " </ll>"
911 " </ll>"
912 "</c>";
913 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
914 assert_non_null(tree);
915
916 /* ancestor */
917 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//ll[a and b]/a/ancestor::node()", &set));
918 assert_int_equal(8, set->count);
919 ly_set_free(set, NULL);
920
921 /* ancestor-or-self */
922 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//ll[a and b]/ancestor-or-self::ll", &set));
923 assert_int_equal(7, set->count);
924 ly_set_free(set, NULL);
925
926 /* attribute */
927 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/l1/@operation", &set));
928 assert_int_equal(0, set->count);
929 ly_set_free(set, NULL);
930
931 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/l1/attribute::key", &set));
932 assert_int_equal(0, set->count);
933 ly_set_free(set, NULL);
934
935 /* child */
936 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/child::l1/child::a", &set));
937 assert_int_equal(3, set->count);
938 ly_set_free(set, NULL);
939
940 /* descendant */
941 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/descendant::c/descendant::b", &set));
942 assert_int_equal(5, set->count);
943 ly_set_free(set, NULL);
944
945 /* descendant-or-self */
946 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//c", &set));
947 assert_int_equal(3, set->count);
948 ly_set_free(set, NULL);
949
950 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/descendant-or-self::node()/c", &set));
951 assert_int_equal(3, set->count);
952 ly_set_free(set, NULL);
953
954 /* following */
955 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/x/following::a", &set));
956 assert_int_equal(7, set->count);
957 ly_set_free(set, NULL);
958
959 /* following-sibling */
960 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/x/following-sibling::ll", &set));
961 assert_int_equal(2, set->count);
962 ly_set_free(set, NULL);
963
964 /* parent */
965 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/child::*/c/parent::l1", &set));
966 assert_int_equal(2, set->count);
967 ly_set_free(set, NULL);
968
969 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/child::c//..", &set));
970 assert_int_equal(8, set->count);
971 ly_set_free(set, NULL);
972
973 /* preceding */
974 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/preceding::a", &set));
975 assert_int_equal(3, set->count);
976 ly_set_free(set, NULL);
977
978 /* preceding-sibling */
979 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/ll/preceding-sibling::node()", &set));
980 assert_int_equal(2, set->count);
981 ly_set_free(set, NULL);
982
983 /* self */
984 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/self::c/ll/ll/b/self::b", &set));
985 assert_int_equal(5, set->count);
986 ly_set_free(set, NULL);
987
988 lyd_free_all(tree);
989}
990
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100991int
992main(void)
Michal Vasko14795a42020-05-22 16:44:44 +0200993{
994 const struct CMUnitTest tests[] = {
aPiecekfff4dca2021-10-07 10:59:53 +0200995 UTEST(test_predicate, setup),
aPiecekadc1e4f2021-10-07 11:15:12 +0200996 UTEST(test_union, setup),
Michal Vaskoe2be5462021-08-04 10:49:42 +0200997 UTEST(test_invalid, setup),
Radek Iša56ca9e42020-09-08 18:42:00 +0200998 UTEST(test_hash, setup),
999 UTEST(test_toplevel, setup),
1000 UTEST(test_atomize, setup),
1001 UTEST(test_canonize, setup),
Michal Vasko93923692021-05-07 15:28:02 +02001002 UTEST(test_derived_from, setup),
Michal Vaskodb08ce52021-10-06 08:57:49 +02001003 UTEST(test_augment, setup),
aPiecekfba75362021-10-07 12:39:48 +02001004 UTEST(test_variables, setup),
Michal Vasko49fec8e2022-05-24 10:28:33 +02001005 UTEST(test_axes, setup),
Michal Vasko14795a42020-05-22 16:44:44 +02001006 };
1007
1008 return cmocka_run_group_tests(tests, NULL, NULL);
1009}