blob: 5ae40f51ab0083e6e053ca1149c2f6084462cf42 [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"
Radek Iša56ca9e42020-09-08 18:42:00 +020063 " container c {\n"
64 " leaf x {\n"
65 " type string;\n"
66 " }\n"
67 " list ll {\n"
68 " key \"a\";\n"
69 " leaf a {\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 " leaf b {\n"
78 " type string;\n"
79 " }\n"
80 " }\n"
81 " }\n"
82 " leaf-list ll2 {\n"
83 " type string;\n"
84 " }\n"
85 " }\n"
86 "}";
Michal Vasko14795a42020-05-22 16:44:44 +020087
88static int
89setup(void **state)
90{
Radek Iša56ca9e42020-09-08 18:42:00 +020091 UTEST_SETUP;
Michal Vasko14795a42020-05-22 16:44:44 +020092
Radek Iša56ca9e42020-09-08 18:42:00 +020093 UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, NULL, NULL);
Michal Vasko14795a42020-05-22 16:44:44 +020094
95 return 0;
96}
97
Michal Vasko14795a42020-05-22 16:44:44 +020098static void
aPiecekfff4dca2021-10-07 10:59:53 +020099test_predicate(void **state)
100{
101 const char *data;
102 struct lyd_node *tree;
103 struct ly_set *set;
104
105 data =
Michal Vasko49fec8e2022-05-24 10:28:33 +0200106 "<foo2 xmlns=\"urn:tests:a\">50</foo2>"
107 "<c xmlns=\"urn:tests:a\">"
108 " <x>val</x>"
109 " <ll>"
110 " <a>key1</a>"
111 " <ll>"
112 " <a>key11</a>"
113 " <b>val11</b>"
114 " </ll>"
115 " <ll>"
116 " <a>key12</a>"
117 " <b>val12</b>"
118 " </ll>"
119 " <ll>"
120 " <a>key13</a>"
121 " <b>val13</b>"
122 " </ll>"
123 " </ll>"
124 " <ll>"
125 " <a>key2</a>"
126 " <ll>"
127 " <a>key21</a>"
128 " <b>val21</b>"
129 " </ll>"
130 " <ll>"
131 " <a>key22</a>"
132 " <b>val22</b>"
133 " </ll>"
134 " </ll>"
135 "</c>";
aPiecekfff4dca2021-10-07 10:59:53 +0200136 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
137 assert_non_null(tree);
138
Michal Vasko49fec8e2022-05-24 10:28:33 +0200139 /* predicate after number */
aPiecekfff4dca2021-10-07 10:59:53 +0200140 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/foo2[4[3 = 3]]", &set));
Michal Vasko49fec8e2022-05-24 10:28:33 +0200141 assert_int_equal(0, set->count);
142 ly_set_free(set, NULL);
143
144 /* reverse axis */
145 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/child::ll[2]/preceding::ll[3]", &set));
146 assert_int_equal(1, set->count);
147 assert_string_equal("key11", lyd_get_value(lyd_child(set->dnodes[0])));
aPiecekfff4dca2021-10-07 10:59:53 +0200148 ly_set_free(set, NULL);
149
150 lyd_free_all(tree);
151}
152
153static void
aPiecekadc1e4f2021-10-07 11:15:12 +0200154test_union(void **state)
155{
156 const char *data;
157 struct lyd_node *tree;
158 struct ly_set *set;
159
160 data =
161 "<l1 xmlns=\"urn:tests:a\">\n"
162 " <a>a1</a>\n"
163 " <b>b1</b>\n"
164 " <c>c1</c>\n"
165 "</l1>\n"
166 "<l1 xmlns=\"urn:tests:a\">\n"
167 " <a>a2</a>\n"
168 " <b>b2</b>\n"
169 "</l1>"
170 "<l1 xmlns=\"urn:tests:a\">\n"
171 " <a>a3</a>\n"
172 " <b>b3</b>\n"
173 " <c>c3</c>\n"
174 "</l1>";
175 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
176 assert_non_null(tree);
177
178 /* Predicate for operand. */
179 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/l1[c[../a = 'a1'] | c]/a", &set));
180 ly_set_free(set, NULL);
181
182 lyd_free_all(tree);
183}
184
185static void
Michal Vaskoe2be5462021-08-04 10:49:42 +0200186test_invalid(void **state)
187{
188 const char *data =
189 "<foo2 xmlns=\"urn:tests:a\">50</foo2>";
190 struct lyd_node *tree;
191 struct ly_set *set;
192
193 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
194 assert_non_null(tree);
195
196 assert_int_equal(LY_EVALID, lyd_find_xpath(tree, "/a:foo2[.=]", &set));
197 assert_null(set);
198
199 assert_int_equal(LY_EVALID, lyd_find_xpath(tree, "/a:", &set));
200 assert_null(set);
201
202 lyd_free_all(tree);
203}
204
205static void
Michal Vasko14795a42020-05-22 16:44:44 +0200206test_hash(void **state)
207{
Michal Vasko14795a42020-05-22 16:44:44 +0200208 const char *data =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100209 "<l1 xmlns=\"urn:tests:a\">\n"
210 " <a>a1</a>\n"
211 " <b>b1</b>\n"
212 " <c>c1</c>\n"
213 "</l1>\n"
214 "<l1 xmlns=\"urn:tests:a\">\n"
215 " <a>a2</a>\n"
216 " <b>b2</b>\n"
217 "</l1>\n"
218 "<l1 xmlns=\"urn:tests:a\">\n"
219 " <a>a3</a>\n"
220 " <b>b3</b>\n"
221 " <c>c3</c>\n"
222 "</l1>\n"
223 "<foo xmlns=\"urn:tests:a\">foo value</foo>\n"
224 "<c xmlns=\"urn:tests:a\">\n"
225 " <x>val</x>\n"
226 " <ll>\n"
227 " <a>val_a</a>\n"
228 " <ll>\n"
229 " <a>val_a</a>\n"
230 " <b>val</b>\n"
231 " </ll>\n"
232 " <ll>\n"
233 " <a>val_b</a>\n"
234 " </ll>\n"
235 " </ll>\n"
236 " <ll>\n"
237 " <a>val_b</a>\n"
238 " <ll>\n"
239 " <a>val_a</a>\n"
240 " </ll>\n"
241 " <ll>\n"
242 " <a>val_b</a>\n"
243 " <b>val</b>\n"
244 " </ll>\n"
245 " </ll>\n"
246 " <ll>\n"
247 " <a>val_c</a>\n"
248 " <ll>\n"
249 " <a>val_a</a>\n"
250 " </ll>\n"
251 " <ll>\n"
252 " <a>val_b</a>\n"
253 " </ll>\n"
254 " </ll>\n"
255 " <ll2>one</ll2>\n"
256 " <ll2>two</ll2>\n"
257 " <ll2>three</ll2>\n"
258 " <ll2>four</ll2>\n"
259 "</c>";
Michal Vasko14795a42020-05-22 16:44:44 +0200260 struct lyd_node *tree, *node;
261 struct ly_set *set;
Michal Vasko14795a42020-05-22 16:44:44 +0200262
Radek Iša56ca9e42020-09-08 18:42:00 +0200263 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 +0200264 assert_non_null(tree);
265
266 /* top-level, so hash table is not ultimately used but instances can be compared based on hashes */
267 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:l1[a='a3'][b='b3']", &set));
268 assert_int_equal(1, set->count);
269
270 node = set->objs[0];
271 assert_string_equal(node->schema->name, "l1");
Radek Krejcia1c1e542020-09-29 16:06:52 +0200272 node = lyd_child(node);
Michal Vasko14795a42020-05-22 16:44:44 +0200273 assert_string_equal(node->schema->name, "a");
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200274 assert_string_equal(lyd_get_value(node), "a3");
Michal Vasko14795a42020-05-22 16:44:44 +0200275
276 ly_set_free(set, NULL);
277
278 /* hashes should be used for both searches (well, there are not enough nested ll instances, so technically not true) */
279 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[a='val_b']/ll[a='val_b']", &set));
280 assert_int_equal(1, set->count);
281
282 node = set->objs[0];
283 assert_string_equal(node->schema->name, "ll");
Radek Krejcia1c1e542020-09-29 16:06:52 +0200284 node = lyd_child(node);
Michal Vasko14795a42020-05-22 16:44:44 +0200285 assert_string_equal(node->schema->name, "a");
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200286 assert_string_equal(lyd_get_value(node), "val_b");
Michal Vasko14795a42020-05-22 16:44:44 +0200287 node = node->next;
288 assert_string_equal(node->schema->name, "b");
289 assert_null(node->next);
290
291 ly_set_free(set, NULL);
292
293 /* hashes are not used */
294 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c//ll[a='val_b']", &set));
295 assert_int_equal(4, set->count);
296
297 ly_set_free(set, NULL);
298
Michal Vasko660cc8f2020-05-25 10:33:19 +0200299 /* hashes used even for leaf-lists */
300 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll2[. = 'three']", &set));
301 assert_int_equal(1, set->count);
302
303 node = set->objs[0];
304 assert_string_equal(node->schema->name, "ll2");
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200305 assert_string_equal(lyd_get_value(node), "three");
Michal Vasko660cc8f2020-05-25 10:33:19 +0200306
307 ly_set_free(set, NULL);
308
Michal Vasko14795a42020-05-22 16:44:44 +0200309 /* not found using hashes */
310 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[a='val_d']", &set));
311 assert_int_equal(0, set->count);
312
313 ly_set_free(set, NULL);
314
315 /* white-spaces are also ok */
316 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[ \na = 'val_c' ]", &set));
317 assert_int_equal(1, set->count);
318
319 ly_set_free(set, NULL);
320
321 lyd_free_all(tree);
Michal Vasko14795a42020-05-22 16:44:44 +0200322}
323
Michal Vasko61ac2f62020-05-25 12:39:51 +0200324static void
325test_toplevel(void **state)
326{
Radek Iša56ca9e42020-09-08 18:42:00 +0200327 const char *schema_b =
328 "module b {\n"
329 " namespace urn:tests:b;\n"
330 " prefix b;\n"
331 " yang-version 1.1;\n"
332 "\n"
333 " list l2 {\n"
334 " key \"a\";\n"
335 " leaf a {\n"
336 " type uint16;\n"
337 " }\n"
338 " leaf b {\n"
339 " type uint16;\n"
340 " }\n"
341 " }\n"
342 "}";
Michal Vasko61ac2f62020-05-25 12:39:51 +0200343 const char *data =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100344 "<l1 xmlns=\"urn:tests:a\">\n"
345 " <a>a1</a>\n"
346 " <b>b1</b>\n"
347 " <c>c1</c>\n"
348 "</l1>\n"
349 "<l1 xmlns=\"urn:tests:a\">\n"
350 " <a>a2</a>\n"
351 " <b>b2</b>\n"
352 "</l1>\n"
353 "<l1 xmlns=\"urn:tests:a\">\n"
354 " <a>a3</a>\n"
355 " <b>b3</b>\n"
356 " <c>c3</c>\n"
357 "</l1>\n"
358 "<foo xmlns=\"urn:tests:a\">foo value</foo>\n"
359 "<l2 xmlns=\"urn:tests:b\">\n"
360 " <a>1</a>\n"
361 " <b>1</b>\n"
362 "</l2>\n"
363 "<l2 xmlns=\"urn:tests:b\">\n"
364 " <a>2</a>\n"
365 " <b>1</b>\n"
366 "</l2>\n"
367 "<l2 xmlns=\"urn:tests:b\">\n"
368 " <a>3</a>\n"
369 " <b>1</b>\n"
370 "</l2>";
Michal Vaskof60e7102020-05-26 10:48:59 +0200371 struct lyd_node *tree;
Michal Vasko61ac2f62020-05-25 12:39:51 +0200372 struct ly_set *set;
Michal Vasko61ac2f62020-05-25 12:39:51 +0200373
Radek Iša56ca9e42020-09-08 18:42:00 +0200374 UTEST_ADD_MODULE(schema_b, LYS_IN_YANG, NULL, NULL);
375
376 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 +0200377 assert_non_null(tree);
378
379 /* all top-level nodes from one module (default container as well) */
380 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:*", &set));
381 assert_int_equal(5, set->count);
382
383 ly_set_free(set, NULL);
384
385 /* all top-level nodes from all modules */
386 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/*", &set));
387 assert_int_equal(8, set->count);
388
389 ly_set_free(set, NULL);
390
391 /* all nodes from one module */
392 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//a:*", &set));
393 assert_int_equal(13, set->count);
394
395 ly_set_free(set, NULL);
396
397 /* all nodes from all modules */
398 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//*", &set));
399 assert_int_equal(22, set->count);
400
401 ly_set_free(set, NULL);
402
403 /* all nodes from all modules #2 */
404 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//.", &set));
405 assert_int_equal(22, set->count);
406
407 ly_set_free(set, NULL);
408
409 lyd_free_all(tree);
Michal Vasko61ac2f62020-05-25 12:39:51 +0200410}
411
Michal Vasko519fd602020-05-26 12:17:39 +0200412static void
413test_atomize(void **state)
414{
Michal Vasko519fd602020-05-26 12:17:39 +0200415 struct ly_set *set;
416 const struct lys_module *mod;
417
Radek Iša56ca9e42020-09-08 18:42:00 +0200418 mod = ly_ctx_get_module_latest(UTEST_LYCTX, "a");
419 assert_non_null(mod);
Michal Vasko519fd602020-05-26 12:17:39 +0200420
421 /* some random paths just making sure the API function works */
Michal Vasko400e9672021-01-11 13:39:17 +0100422 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:*", 0, &set));
Michal Vasko93923692021-05-07 15:28:02 +0200423 assert_int_equal(5, set->count);
Michal Vasko519fd602020-05-26 12:17:39 +0200424 ly_set_free(set, NULL);
425
426 /* all nodes from all modules (including internal, which can change easily, so check just the test modules) */
Michal Vasko400e9672021-01-11 13:39:17 +0100427 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "//.", 0, &set));
Michal Vasko93923692021-05-07 15:28:02 +0200428 assert_in_range(set->count, 17, UINT32_MAX);
Michal Vasko519fd602020-05-26 12:17:39 +0200429 ly_set_free(set, NULL);
430
Michal Vasko400e9672021-01-11 13:39:17 +0100431 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:c/ll[a='val1']/ll[a='val2']/b", 0, &set));
432 assert_int_equal(6, set->count);
Michal Vasko49fec8e2022-05-24 10:28:33 +0200433 ly_set_free(set, NULL);
Michal Vasko519fd602020-05-26 12:17:39 +0200434
Michal Vasko49fec8e2022-05-24 10:28:33 +0200435 /*
436 * axes
437 */
438
439 /* ancestor */
440 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "//ll[a and b]/a/ancestor::node()", 0, &set));
441 assert_int_equal(6, set->count);
442 ly_set_free(set, NULL);
443
444 /* ancestor-or-self */
445 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "//ll[a and b]/ancestor-or-self::ll", 0, &set));
446 assert_int_equal(5, set->count);
447 ly_set_free(set, NULL);
448
449 /* attribute */
450 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/l1/attribute::key", 0, &set));
451 assert_int_equal(1, set->count);
452 ly_set_free(set, NULL);
453
454 /* child */
455 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/child::l1/child::a", 0, &set));
456 assert_int_equal(2, set->count);
457 ly_set_free(set, NULL);
458
459 /* descendant */
460 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/descendant::c/descendant::b", 0, &set));
461 assert_int_equal(3, set->count);
462 ly_set_free(set, NULL);
463
464 /* descendant-or-self */
465 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:*/descendant-or-self::c", 0, &set));
466 assert_int_equal(6, set->count);
467 ly_set_free(set, NULL);
468
469 /* following */
470 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/x/following::a", 0, &set));
471 assert_int_equal(4, set->count);
472 ly_set_free(set, NULL);
473
474 /* following-sibling */
475 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/x/following-sibling::ll", 0, &set));
476 assert_int_equal(3, set->count);
477 ly_set_free(set, NULL);
478
479 /* parent */
480 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/child::a:*/c/parent::l1", 0, &set));
481 assert_int_equal(6, set->count);
482 ly_set_free(set, NULL);
483
484 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/child::a:c//..", 0, &set));
485 assert_int_equal(8, set->count);
486 ly_set_free(set, NULL);
487
488 /* preceding */
489 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/preceding::a", 0, &set));
490 assert_int_equal(2, set->count);
491 ly_set_free(set, NULL);
492
493 /* preceding-sibling */
494 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/ll/preceding-sibling::node()", 0, &set));
495 assert_int_equal(3, set->count);
496 ly_set_free(set, NULL);
497
498 /* self */
499 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/self::c/ll/ll/b/self::b", 0, &set));
500 assert_int_equal(4, set->count);
Michal Vasko519fd602020-05-26 12:17:39 +0200501 ly_set_free(set, NULL);
502}
503
Michal Vasko4c7763f2020-07-27 17:40:37 +0200504static void
505test_canonize(void **state)
506{
Michal Vasko4c7763f2020-07-27 17:40:37 +0200507 const char *data =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100508 "<foo2 xmlns=\"urn:tests:a\">50</foo2>";
Michal Vasko4c7763f2020-07-27 17:40:37 +0200509 struct lyd_node *tree;
510 struct ly_set *set;
511
Radek Iša56ca9e42020-09-08 18:42:00 +0200512 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 +0200513 assert_non_null(tree);
514
515 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo2[.='050']", &set));
516 assert_int_equal(1, set->count);
517 ly_set_free(set, NULL);
518
519 /* TODO more use-cases once there are some type plugins that have canonical values */
520
521 lyd_free_all(tree);
Michal Vasko4c7763f2020-07-27 17:40:37 +0200522}
523
Michal Vasko93923692021-05-07 15:28:02 +0200524static void
525test_derived_from(void **state)
526{
527 const char *data =
528 "<foo3 xmlns=\"urn:tests:a\">id_c</foo3>";
529 struct lyd_node *tree;
530 struct ly_set *set;
531
532 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
533 assert_non_null(tree);
534
535 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo3[derived-from(., 'a:id_b')]", &set));
536 assert_int_equal(1, set->count);
537 ly_set_free(set, NULL);
538
539 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo3[derived-from(., 'a:id_a')]", &set));
540 assert_int_equal(1, set->count);
541 ly_set_free(set, NULL);
542
543 lyd_free_all(tree);
544}
545
Michal Vaskodb08ce52021-10-06 08:57:49 +0200546static void
547test_augment(void **state)
548{
549 const char *schema_b =
550 "module b {\n"
551 " namespace urn:tests:b;\n"
552 " prefix b;\n"
553 " yang-version 1.1;\n"
554 "\n"
555 " import a {\n"
556 " prefix a;\n"
557 " }\n"
558 "\n"
559 " augment /a:c {\n"
560 " leaf a {\n"
561 " type uint16;\n"
562 " }\n"
563 " }\n"
564 "}";
565 const char *data =
566 "<c xmlns=\"urn:tests:a\">\n"
567 " <x>value</x>\n"
568 " <ll>\n"
569 " <a>key</a>\n"
570 " </ll>\n"
571 " <a xmlns=\"urn:tests:b\">25</a>\n"
572 " <ll2>c1</ll2>\n"
573 "</c>";
574 struct lyd_node *tree;
575 struct ly_set *set;
576
577 UTEST_ADD_MODULE(schema_b, LYS_IN_YANG, NULL, NULL);
578
579 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
580 assert_non_null(tree);
581
582 /* get all children ignoring their module */
583 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/*", &set));
584 assert_int_equal(4, set->count);
585
586 ly_set_free(set, NULL);
587
588 lyd_free_all(tree);
589}
590
aPiecekfba75362021-10-07 12:39:48 +0200591static void
592test_variables(void **state)
593{
594 struct lyd_node *tree, *node;
595 struct ly_set *set;
596 const char *data;
597 struct lyxp_var *vars = NULL;
598
599#define LOCAL_SETUP(DATA, TREE) \
600 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, DATA, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &TREE)); \
601 assert_non_null(TREE);
602
603#define SET_NODE(NODE, SET, INDEX) \
604 assert_non_null(SET); \
605 assert_true(INDEX < SET->count); \
606 NODE = SET->objs[INDEX];
607
608#define LOCAL_TEARDOWN(SET, TREE, VARS) \
609 ly_set_free(SET, NULL); \
610 lyd_free_all(TREE); \
611 lyxp_vars_free(VARS); \
612 vars = NULL;
613
614 /* Eval variable to number. */
615 data =
616 "<l1 xmlns=\"urn:tests:a\">\n"
617 " <a>a1</a>\n"
618 " <b>b1</b>\n"
619 " <c>c1</c>\n"
620 "</l1>"
621 "<l1 xmlns=\"urn:tests:a\">\n"
622 " <a>a2</a>\n"
623 " <b>b2</b>\n"
624 " <c>c2</c>\n"
625 "</l1>";
626 LOCAL_SETUP(data, tree);
627 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "2"));
628 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var]/a", vars, &set));
629 SET_NODE(node, set, 0);
630 assert_string_equal(lyd_get_value(node), "a2");
631 LOCAL_TEARDOWN(set, tree, vars);
632
633 /* Eval variable to string. */
634 data =
635 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
636 LOCAL_SETUP(data, tree);
637 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "\"mstr\""));
638 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/foo[text() = $var]", vars, &set));
639 SET_NODE(node, set, 0);
640 assert_string_equal(lyd_get_value(node), "mstr");
641 LOCAL_TEARDOWN(set, tree, vars);
642
643 /* Eval variable to set of nodes. */
644 data =
645 "<l1 xmlns=\"urn:tests:a\">\n"
646 " <a>a1</a>\n"
647 " <b>b1</b>\n"
648 "</l1>"
649 "<l1 xmlns=\"urn:tests:a\">\n"
650 " <a>a2</a>\n"
651 " <b>b2</b>\n"
652 " <c>c2</c>\n"
653 "</l1>";
654 LOCAL_SETUP(data, tree);
655 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "c"));
656 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var]/a", vars, &set));
657 SET_NODE(node, set, 0);
658 assert_string_equal(lyd_get_value(node), "a2");
659 LOCAL_TEARDOWN(set, tree, vars);
660
661 /* Variable in union expr. */
662 data =
663 "<l1 xmlns=\"urn:tests:a\">\n"
664 " <a>a1</a>\n"
665 " <b>b1</b>\n"
666 " <c>c1</c>\n"
667 "</l1>"
668 "<l1 xmlns=\"urn:tests:a\">\n"
669 " <a>a2</a>\n"
670 " <b>b2</b>\n"
671 " <c>c2</c>\n"
672 "</l1>"
673 "<l1 xmlns=\"urn:tests:a\">\n"
674 " <a>a3</a>\n"
675 " <b>b3</b>\n"
676 " <c>c3</c>\n"
677 "</l1>";
678 LOCAL_SETUP(data, tree);
679 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "c[../a = 'a3']"));
680 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[c[../a = 'a1'] | $var]/a", vars, &set));
681 SET_NODE(node, set, 0);
682 assert_string_equal(lyd_get_value(node), "a1");
683 SET_NODE(node, set, 1);
684 assert_string_equal(lyd_get_value(node), "a3");
685 assert_int_equal(set->count, 2);
686 LOCAL_TEARDOWN(set, tree, vars);
687
688 /* Predicate after variable. */
689 data =
690 "<l1 xmlns=\"urn:tests:a\">\n"
691 " <a>a1</a>\n"
692 " <b>b1</b>\n"
693 " <c>c1</c>\n"
694 "</l1>"
695 "<l1 xmlns=\"urn:tests:a\">\n"
696 " <a>a2</a>\n"
697 " <b>b2</b>\n"
698 " <c>c2</c>\n"
699 "</l1>";
700 LOCAL_SETUP(data, tree);
701 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "c"));
702 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var[../a = 'a1']]/a", vars, &set));
703 SET_NODE(node, set, 0);
704 assert_string_equal(lyd_get_value(node), "a1");
705 LOCAL_TEARDOWN(set, tree, vars);
706
707 /* Variable in variable. */
708 data =
709 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
710 LOCAL_SETUP(data, tree);
711 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "$var2"));
712 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var2", "\"mstr\""));
713 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/foo[text() = $var]", vars, &set));
714 SET_NODE(node, set, 0);
715 assert_string_equal(lyd_get_value(node), "mstr");
716 LOCAL_TEARDOWN(set, tree, vars);
717
718 /* Compare two variables. */
719 data =
720 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
721 LOCAL_SETUP(data, tree);
722 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "\"str\""));
723 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var2", "\"str\""));
724 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/foo[$var1 = $var2]", vars, &set));
725 SET_NODE(node, set, 0);
726 assert_string_equal(lyd_get_value(node), "mstr");
727 LOCAL_TEARDOWN(set, tree, vars);
728
729 /* Arithmetic operation with variable. */
730 data =
731 "<foo2 xmlns=\"urn:tests:a\">4</foo2>";
732 LOCAL_SETUP(data, tree);
733 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "2"));
734 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/foo2[.= ($var1 * 2)]", vars, &set));
735 SET_NODE(node, set, 0);
736 assert_string_equal(lyd_get_value(node), "4");
737 LOCAL_TEARDOWN(set, tree, vars);
738
739 /* Variable as function parameter. */
740 data =
741 "<l1 xmlns=\"urn:tests:a\">\n"
742 " <a>a1</a>\n"
743 " <b>b1</b>\n"
744 " <c>c1</c>\n"
745 "</l1>"
746 "<l1 xmlns=\"urn:tests:a\">\n"
747 " <a>a2</a>\n"
748 " <b>b2</b>\n"
749 "</l1>";
750 LOCAL_SETUP(data, tree);
751 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "./c"));
752 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[count($var) = 1]/a", vars, &set));
753 SET_NODE(node, set, 0);
754 assert_string_equal(lyd_get_value(node), "a1");
755 LOCAL_TEARDOWN(set, tree, vars);
756
757 /* Variable in path expr. */
758 /* NOTE: The variable can only be at the beginning of the expression path. */
759 data =
760 "<l1 xmlns=\"urn:tests:a\">\n"
761 " <a>a1</a>\n"
762 " <b>b1</b>\n"
763 " <c>c1</c>\n"
764 "</l1>"
765 "<l1 xmlns=\"urn:tests:a\">\n"
766 " <a>a2</a>\n"
767 " <b>b2</b>\n"
768 "</l1>";
769 LOCAL_SETUP(data, tree);
770 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "/l1"));
771 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var/a]", vars, &set));
772 assert_int_equal(set->count, 2);
773 LOCAL_TEARDOWN(set, tree, vars);
774
775 /* Variable as function. */
776 data =
777 "<l1 xmlns=\"urn:tests:a\">\n"
778 " <a>a1</a>\n"
779 " <b>b1</b>\n"
780 " <c>c1</c>\n"
781 "</l1>"
782 "<l1 xmlns=\"urn:tests:a\">\n"
783 " <a>a2</a>\n"
784 " <b>b2</b>\n"
785 "</l1>";
786 LOCAL_SETUP(data, tree);
787 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "position()"));
788 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var = 2]/a", vars, &set));
789 SET_NODE(node, set, 0);
790 assert_string_equal(lyd_get_value(node), "a2");
791 LOCAL_TEARDOWN(set, tree, vars);
792
793 /* Dynamic change of value. */
794 data =
795 "<l1 xmlns=\"urn:tests:a\">\n"
796 " <a>a1</a>\n"
797 " <b>b1</b>\n"
798 " <c>c1</c>\n"
799 "</l1>"
800 "<l1 xmlns=\"urn:tests:a\">\n"
801 " <a>a2</a>\n"
802 " <b>b2</b>\n"
803 " <c>c2</c>\n"
804 "</l1>";
805 LOCAL_SETUP(data, tree);
806 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "1"));
807 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var]/a", vars, &set));
808 SET_NODE(node, set, 0);
809 assert_string_equal(lyd_get_value(node), "a1");
810 ly_set_free(set, NULL);
811 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "2"));
812 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var]/a", vars, &set));
813 SET_NODE(node, set, 0);
814 assert_string_equal(lyd_get_value(node), "a2");
815 LOCAL_TEARDOWN(set, tree, vars);
816
817 /* Variable not defined. */
818 data =
819 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
820 LOCAL_SETUP(data, tree);
821 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "\"mstr\""));
822 assert_int_equal(LY_ENOTFOUND, lyd_find_xpath2(tree, "/foo[text() = $var55]", vars, &set));
823 LOCAL_TEARDOWN(set, tree, vars);
824
825 /* Syntax error in value. */
826 data =
827 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
828 LOCAL_SETUP(data, tree);
829 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "\""));
830 assert_int_equal(LY_EVALID, lyd_find_xpath2(tree, "/foo[$var]", vars, &set));
831 LOCAL_TEARDOWN(set, tree, vars);
832
833 /* Prefix is not supported. */
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, "var", "\""));
838 assert_int_equal(LY_EVALID, lyd_find_xpath2(tree, "/foo[$pref:var]", vars, &set));
839 assert_string_equal("Variable with prefix is not supported.", _UC->err_msg);
840 LOCAL_TEARDOWN(set, tree, vars);
841
842#undef LOCAL_SETUP
843#undef LOCAL_TEARDOWN
844}
845
Michal Vasko49fec8e2022-05-24 10:28:33 +0200846static void
847test_axes(void **state)
848{
849 const char *data;
850 struct lyd_node *tree;
851 struct ly_set *set;
852
853 data =
854 "<l1 xmlns=\"urn:tests:a\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\">\n"
855 " <a>a1</a>\n"
856 " <b yang:operation=\"replace\">b1</b>\n"
857 " <c yang:operation=\"none\">c1</c>\n"
858 "</l1>\n"
859 "<l1 xmlns=\"urn:tests:a\">\n"
860 " <a>a2</a>\n"
861 " <b>b2</b>\n"
862 "</l1>"
863 "<l1 xmlns=\"urn:tests:a\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\">\n"
864 " <a yang:operation=\"none\" yang:key=\"no-key\">a3</a>\n"
865 " <b>b3</b>\n"
866 " <c yang:value=\"no-val\">c3</c>\n"
867 "</l1>"
868 "<c xmlns=\"urn:tests:a\">"
869 " <x>val</x>"
870 " <ll>"
871 " <a>key1</a>"
872 " <ll>"
873 " <a>key11</a>"
874 " <b>val11</b>"
875 " </ll>"
876 " <ll>"
877 " <a>key12</a>"
878 " <b>val12</b>"
879 " </ll>"
880 " <ll>"
881 " <a>key13</a>"
882 " <b>val13</b>"
883 " </ll>"
884 " </ll>"
885 " <ll>"
886 " <a>key2</a>"
887 " <ll>"
888 " <a>key21</a>"
889 " <b>val21</b>"
890 " </ll>"
891 " <ll>"
892 " <a>key22</a>"
893 " <b>val22</b>"
894 " </ll>"
895 " </ll>"
896 "</c>";
897 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
898 assert_non_null(tree);
899
900 /* ancestor */
901 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//ll[a and b]/a/ancestor::node()", &set));
902 assert_int_equal(8, set->count);
903 ly_set_free(set, NULL);
904
905 /* ancestor-or-self */
906 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//ll[a and b]/ancestor-or-self::ll", &set));
907 assert_int_equal(7, set->count);
908 ly_set_free(set, NULL);
909
910 /* attribute */
911 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/l1/@operation", &set));
912 assert_int_equal(0, set->count);
913 ly_set_free(set, NULL);
914
915 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/l1/attribute::key", &set));
916 assert_int_equal(0, set->count);
917 ly_set_free(set, NULL);
918
919 /* child */
920 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/child::l1/child::a", &set));
921 assert_int_equal(3, set->count);
922 ly_set_free(set, NULL);
923
924 /* descendant */
925 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/descendant::c/descendant::b", &set));
926 assert_int_equal(5, set->count);
927 ly_set_free(set, NULL);
928
929 /* descendant-or-self */
930 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//c", &set));
931 assert_int_equal(3, set->count);
932 ly_set_free(set, NULL);
933
934 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/descendant-or-self::node()/c", &set));
935 assert_int_equal(3, set->count);
936 ly_set_free(set, NULL);
937
938 /* following */
939 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/x/following::a", &set));
940 assert_int_equal(7, set->count);
941 ly_set_free(set, NULL);
942
943 /* following-sibling */
944 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/x/following-sibling::ll", &set));
945 assert_int_equal(2, set->count);
946 ly_set_free(set, NULL);
947
948 /* parent */
949 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/child::*/c/parent::l1", &set));
950 assert_int_equal(2, set->count);
951 ly_set_free(set, NULL);
952
953 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/child::c//..", &set));
954 assert_int_equal(8, set->count);
955 ly_set_free(set, NULL);
956
957 /* preceding */
958 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/preceding::a", &set));
959 assert_int_equal(3, set->count);
960 ly_set_free(set, NULL);
961
962 /* preceding-sibling */
963 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/ll/preceding-sibling::node()", &set));
964 assert_int_equal(2, set->count);
965 ly_set_free(set, NULL);
966
967 /* self */
968 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/self::c/ll/ll/b/self::b", &set));
969 assert_int_equal(5, set->count);
970 ly_set_free(set, NULL);
971
972 lyd_free_all(tree);
973}
974
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100975int
976main(void)
Michal Vasko14795a42020-05-22 16:44:44 +0200977{
978 const struct CMUnitTest tests[] = {
aPiecekfff4dca2021-10-07 10:59:53 +0200979 UTEST(test_predicate, setup),
aPiecekadc1e4f2021-10-07 11:15:12 +0200980 UTEST(test_union, setup),
Michal Vaskoe2be5462021-08-04 10:49:42 +0200981 UTEST(test_invalid, setup),
Radek Iša56ca9e42020-09-08 18:42:00 +0200982 UTEST(test_hash, setup),
983 UTEST(test_toplevel, setup),
984 UTEST(test_atomize, setup),
985 UTEST(test_canonize, setup),
Michal Vasko93923692021-05-07 15:28:02 +0200986 UTEST(test_derived_from, setup),
Michal Vaskodb08ce52021-10-06 08:57:49 +0200987 UTEST(test_augment, setup),
aPiecekfba75362021-10-07 12:39:48 +0200988 UTEST(test_variables, setup),
Michal Vasko49fec8e2022-05-24 10:28:33 +0200989 UTEST(test_axes, setup),
Michal Vasko14795a42020-05-22 16:44:44 +0200990 };
991
992 return cmocka_run_group_tests(tests, NULL, NULL);
993}