blob: 7a2785b36f5c78a2b00d310779c36ad69f7cbe24 [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"
Michal Vaskoc7304482023-11-30 15:59:30 +010091 "\n"
92 " rpc r {\n"
93 " input {\n"
94 " leaf l {\n"
95 " type string;\n"
96 " }\n"
97 " }\n"
98 " output {\n"
99 " leaf l {\n"
100 " type string;\n"
101 " }\n"
102 " }\n"
103 " }\n"
Radek Iša56ca9e42020-09-08 18:42:00 +0200104 "}";
Michal Vasko14795a42020-05-22 16:44:44 +0200105
106static int
107setup(void **state)
108{
Radek Iša56ca9e42020-09-08 18:42:00 +0200109 UTEST_SETUP;
Michal Vasko14795a42020-05-22 16:44:44 +0200110
Radek Iša56ca9e42020-09-08 18:42:00 +0200111 UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, NULL, NULL);
Michal Vaskoa353cce2022-11-14 10:09:55 +0100112 lys_parse_path(UTEST_LYCTX, TESTS_DIR_MODULES_YANG "/ietf-interfaces@2014-05-08.yang", LYS_IN_YANG, NULL);
Michal Vasko14795a42020-05-22 16:44:44 +0200113
114 return 0;
115}
116
Michal Vasko14795a42020-05-22 16:44:44 +0200117static void
aPiecekfff4dca2021-10-07 10:59:53 +0200118test_predicate(void **state)
119{
120 const char *data;
121 struct lyd_node *tree;
122 struct ly_set *set;
123
124 data =
Michal Vasko49fec8e2022-05-24 10:28:33 +0200125 "<foo2 xmlns=\"urn:tests:a\">50</foo2>"
Michal Vasko3d969ff2022-07-29 15:02:08 +0200126 "<l1 xmlns=\"urn:tests:a\">"
127 " <a>a1</a>"
128 " <b>b1</b>"
129 " <c>c1</c>"
130 "</l1>"
131 "<l1 xmlns=\"urn:tests:a\">"
132 " <a>a2</a>"
133 " <b>b2</b>"
134 "</l1>"
135 "<l1 xmlns=\"urn:tests:a\">"
136 " <a>a3</a>"
137 " <b>b3</b>"
138 "</l1>"
139 "<l1 xmlns=\"urn:tests:a\">"
140 " <a>a4</a>"
141 " <b>b4</b>"
142 " <c>c4</c>"
143 "</l1>"
144 "<l1 xmlns=\"urn:tests:a\">"
145 " <a>a5</a>"
146 " <b>b5</b>"
147 " <c>c5</c>"
148 "</l1>"
Michal Vasko49fec8e2022-05-24 10:28:33 +0200149 "<c xmlns=\"urn:tests:a\">"
Michal Vasko3d969ff2022-07-29 15:02:08 +0200150 " <x>key2</x>"
Michal Vasko49fec8e2022-05-24 10:28:33 +0200151 " <ll>"
152 " <a>key1</a>"
153 " <ll>"
154 " <a>key11</a>"
155 " <b>val11</b>"
156 " </ll>"
157 " <ll>"
158 " <a>key12</a>"
159 " <b>val12</b>"
160 " </ll>"
161 " <ll>"
162 " <a>key13</a>"
163 " <b>val13</b>"
164 " </ll>"
165 " </ll>"
166 " <ll>"
167 " <a>key2</a>"
168 " <ll>"
169 " <a>key21</a>"
170 " <b>val21</b>"
171 " </ll>"
172 " <ll>"
173 " <a>key22</a>"
174 " <b>val22</b>"
175 " </ll>"
176 " </ll>"
Michal Vasko3d969ff2022-07-29 15:02:08 +0200177 " <ll>"
178 " <a>key3</a>"
179 " <ll>"
180 " <a>key31</a>"
181 " <b>val31</b>"
182 " </ll>"
183 " <ll>"
184 " <a>key32</a>"
185 " <b>val32</b>"
186 " </ll>"
187 " </ll>"
Michal Vasko49fec8e2022-05-24 10:28:33 +0200188 "</c>";
aPiecekfff4dca2021-10-07 10:59:53 +0200189 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
190 assert_non_null(tree);
191
Michal Vasko49fec8e2022-05-24 10:28:33 +0200192 /* predicate after number */
aPiecekfff4dca2021-10-07 10:59:53 +0200193 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/foo2[4[3 = 3]]", &set));
Michal Vasko49fec8e2022-05-24 10:28:33 +0200194 assert_int_equal(0, set->count);
195 ly_set_free(set, NULL);
196
197 /* reverse axis */
198 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/child::ll[2]/preceding::ll[3]", &set));
199 assert_int_equal(1, set->count);
200 assert_string_equal("key11", lyd_get_value(lyd_child(set->dnodes[0])));
aPiecekfff4dca2021-10-07 10:59:53 +0200201 ly_set_free(set, NULL);
202
Michal Vasko3d969ff2022-07-29 15:02:08 +0200203 /* special predicate evaluated using hashes */
204 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:l1[a=concat('a', '1')][b=substring('ab1',2)]", &set));
205 assert_int_equal(1, set->count);
206 ly_set_free(set, NULL);
207
208 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[a=../x]", &set));
209 assert_int_equal(1, set->count);
210 ly_set_free(set, NULL);
211
212 /* cannot use hashes */
213 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[a=substring(ll/a,1,4)]", &set));
214 assert_int_equal(3, set->count);
215 ly_set_free(set, NULL);
216
Michal Vasko3ef7e252022-11-16 08:29:49 +0100217 /* nested predicate */
218 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/a:ll[a:a=string(/a:l1[a:a='foo']/a:a)]/a:a", &set));
219 assert_int_equal(0, set->count);
220 ly_set_free(set, NULL);
221
aPiecekfff4dca2021-10-07 10:59:53 +0200222 lyd_free_all(tree);
223}
224
225static void
aPiecekadc1e4f2021-10-07 11:15:12 +0200226test_union(void **state)
227{
228 const char *data;
229 struct lyd_node *tree;
230 struct ly_set *set;
231
232 data =
233 "<l1 xmlns=\"urn:tests:a\">\n"
234 " <a>a1</a>\n"
235 " <b>b1</b>\n"
236 " <c>c1</c>\n"
237 "</l1>\n"
238 "<l1 xmlns=\"urn:tests:a\">\n"
239 " <a>a2</a>\n"
240 " <b>b2</b>\n"
241 "</l1>"
242 "<l1 xmlns=\"urn:tests:a\">\n"
243 " <a>a3</a>\n"
244 " <b>b3</b>\n"
245 " <c>c3</c>\n"
246 "</l1>";
247 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
248 assert_non_null(tree);
249
250 /* Predicate for operand. */
251 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/l1[c[../a = 'a1'] | c]/a", &set));
252 ly_set_free(set, NULL);
253
254 lyd_free_all(tree);
255}
256
257static void
Michal Vaskoe2be5462021-08-04 10:49:42 +0200258test_invalid(void **state)
259{
260 const char *data =
261 "<foo2 xmlns=\"urn:tests:a\">50</foo2>";
262 struct lyd_node *tree;
263 struct ly_set *set;
264
265 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
266 assert_non_null(tree);
267
268 assert_int_equal(LY_EVALID, lyd_find_xpath(tree, "/a:foo2[.=]", &set));
269 assert_null(set);
Michal Vasko7a266772024-01-23 11:02:38 +0100270 CHECK_LOG_CTX("Unexpected XPath token \"]\" (\"]\").", NULL, 0);
Michal Vaskoe2be5462021-08-04 10:49:42 +0200271
272 assert_int_equal(LY_EVALID, lyd_find_xpath(tree, "/a:", &set));
273 assert_null(set);
Michal Vasko7a266772024-01-23 11:02:38 +0100274 CHECK_LOG_CTX("Invalid character 'a'[2] of expression '/a:'.", NULL, 0);
Michal Vaskoe2be5462021-08-04 10:49:42 +0200275
276 lyd_free_all(tree);
277}
278
279static void
Michal Vasko14795a42020-05-22 16:44:44 +0200280test_hash(void **state)
281{
Michal Vasko14795a42020-05-22 16:44:44 +0200282 const char *data =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100283 "<l1 xmlns=\"urn:tests:a\">\n"
284 " <a>a1</a>\n"
285 " <b>b1</b>\n"
286 " <c>c1</c>\n"
287 "</l1>\n"
288 "<l1 xmlns=\"urn:tests:a\">\n"
289 " <a>a2</a>\n"
290 " <b>b2</b>\n"
291 "</l1>\n"
292 "<l1 xmlns=\"urn:tests:a\">\n"
293 " <a>a3</a>\n"
294 " <b>b3</b>\n"
295 " <c>c3</c>\n"
296 "</l1>\n"
297 "<foo xmlns=\"urn:tests:a\">foo value</foo>\n"
298 "<c xmlns=\"urn:tests:a\">\n"
299 " <x>val</x>\n"
300 " <ll>\n"
301 " <a>val_a</a>\n"
302 " <ll>\n"
303 " <a>val_a</a>\n"
304 " <b>val</b>\n"
305 " </ll>\n"
306 " <ll>\n"
307 " <a>val_b</a>\n"
308 " </ll>\n"
309 " </ll>\n"
310 " <ll>\n"
311 " <a>val_b</a>\n"
312 " <ll>\n"
313 " <a>val_a</a>\n"
314 " </ll>\n"
315 " <ll>\n"
316 " <a>val_b</a>\n"
317 " <b>val</b>\n"
318 " </ll>\n"
319 " </ll>\n"
320 " <ll>\n"
321 " <a>val_c</a>\n"
322 " <ll>\n"
323 " <a>val_a</a>\n"
324 " </ll>\n"
325 " <ll>\n"
326 " <a>val_b</a>\n"
327 " </ll>\n"
328 " </ll>\n"
329 " <ll2>one</ll2>\n"
330 " <ll2>two</ll2>\n"
331 " <ll2>three</ll2>\n"
332 " <ll2>four</ll2>\n"
333 "</c>";
Michal Vasko14795a42020-05-22 16:44:44 +0200334 struct lyd_node *tree, *node;
335 struct ly_set *set;
Michal Vasko14795a42020-05-22 16:44:44 +0200336
Radek Iša56ca9e42020-09-08 18:42:00 +0200337 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 +0200338 assert_non_null(tree);
339
340 /* top-level, so hash table is not ultimately used but instances can be compared based on hashes */
341 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:l1[a='a3'][b='b3']", &set));
342 assert_int_equal(1, set->count);
343
344 node = set->objs[0];
345 assert_string_equal(node->schema->name, "l1");
Radek Krejcia1c1e542020-09-29 16:06:52 +0200346 node = lyd_child(node);
Michal Vasko14795a42020-05-22 16:44:44 +0200347 assert_string_equal(node->schema->name, "a");
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200348 assert_string_equal(lyd_get_value(node), "a3");
Michal Vasko14795a42020-05-22 16:44:44 +0200349
350 ly_set_free(set, NULL);
351
352 /* hashes should be used for both searches (well, there are not enough nested ll instances, so technically not true) */
353 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[a='val_b']/ll[a='val_b']", &set));
354 assert_int_equal(1, set->count);
355
356 node = set->objs[0];
357 assert_string_equal(node->schema->name, "ll");
Radek Krejcia1c1e542020-09-29 16:06:52 +0200358 node = lyd_child(node);
Michal Vasko14795a42020-05-22 16:44:44 +0200359 assert_string_equal(node->schema->name, "a");
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200360 assert_string_equal(lyd_get_value(node), "val_b");
Michal Vasko14795a42020-05-22 16:44:44 +0200361 node = node->next;
362 assert_string_equal(node->schema->name, "b");
363 assert_null(node->next);
364
365 ly_set_free(set, NULL);
366
367 /* hashes are not used */
368 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c//ll[a='val_b']", &set));
369 assert_int_equal(4, set->count);
370
371 ly_set_free(set, NULL);
372
Michal Vasko660cc8f2020-05-25 10:33:19 +0200373 /* hashes used even for leaf-lists */
374 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll2[. = 'three']", &set));
375 assert_int_equal(1, set->count);
376
377 node = set->objs[0];
378 assert_string_equal(node->schema->name, "ll2");
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200379 assert_string_equal(lyd_get_value(node), "three");
Michal Vasko660cc8f2020-05-25 10:33:19 +0200380
381 ly_set_free(set, NULL);
382
Michal Vasko14795a42020-05-22 16:44:44 +0200383 /* not found using hashes */
384 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[a='val_d']", &set));
385 assert_int_equal(0, set->count);
386
387 ly_set_free(set, NULL);
388
389 /* white-spaces are also ok */
390 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[ \na = 'val_c' ]", &set));
391 assert_int_equal(1, set->count);
392
393 ly_set_free(set, NULL);
394
395 lyd_free_all(tree);
Michal Vasko14795a42020-05-22 16:44:44 +0200396}
397
Michal Vasko61ac2f62020-05-25 12:39:51 +0200398static void
Michal Vaskoc7304482023-11-30 15:59:30 +0100399test_rpc(void **state)
400{
401 const char *data =
402 "<r xmlns=\"urn:tests:a\">\n"
403 " <l>val</l>\n"
404 "</r>";
405 struct ly_in *in;
406 struct lyd_node *tree;
407 struct ly_set *set;
408
409 assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
410 assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_XML, LYD_TYPE_REPLY_YANG, &tree, NULL));
411 ly_in_free(in, 0);
412 assert_non_null(tree);
413
414 /* name collision input/output, hashes are not used */
415 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:r/l", &set));
416 assert_int_equal(1, set->count);
417
418 ly_set_free(set, NULL);
419
420 lyd_free_all(tree);
421}
422
423static void
Michal Vasko61ac2f62020-05-25 12:39:51 +0200424test_toplevel(void **state)
425{
Radek Iša56ca9e42020-09-08 18:42:00 +0200426 const char *schema_b =
427 "module b {\n"
428 " namespace urn:tests:b;\n"
429 " prefix b;\n"
430 " yang-version 1.1;\n"
431 "\n"
432 " list l2 {\n"
433 " key \"a\";\n"
434 " leaf a {\n"
435 " type uint16;\n"
436 " }\n"
437 " leaf b {\n"
438 " type uint16;\n"
439 " }\n"
440 " }\n"
441 "}";
Michal Vasko61ac2f62020-05-25 12:39:51 +0200442 const char *data =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100443 "<l1 xmlns=\"urn:tests:a\">\n"
444 " <a>a1</a>\n"
445 " <b>b1</b>\n"
446 " <c>c1</c>\n"
447 "</l1>\n"
448 "<l1 xmlns=\"urn:tests:a\">\n"
449 " <a>a2</a>\n"
450 " <b>b2</b>\n"
451 "</l1>\n"
452 "<l1 xmlns=\"urn:tests:a\">\n"
453 " <a>a3</a>\n"
454 " <b>b3</b>\n"
455 " <c>c3</c>\n"
456 "</l1>\n"
457 "<foo xmlns=\"urn:tests:a\">foo value</foo>\n"
458 "<l2 xmlns=\"urn:tests:b\">\n"
459 " <a>1</a>\n"
460 " <b>1</b>\n"
461 "</l2>\n"
462 "<l2 xmlns=\"urn:tests:b\">\n"
463 " <a>2</a>\n"
464 " <b>1</b>\n"
465 "</l2>\n"
466 "<l2 xmlns=\"urn:tests:b\">\n"
467 " <a>3</a>\n"
468 " <b>1</b>\n"
469 "</l2>";
Michal Vaskof60e7102020-05-26 10:48:59 +0200470 struct lyd_node *tree;
Michal Vasko61ac2f62020-05-25 12:39:51 +0200471 struct ly_set *set;
Michal Vasko61ac2f62020-05-25 12:39:51 +0200472
Radek Iša56ca9e42020-09-08 18:42:00 +0200473 UTEST_ADD_MODULE(schema_b, LYS_IN_YANG, NULL, NULL);
474
475 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 +0200476 assert_non_null(tree);
477
478 /* all top-level nodes from one module (default container as well) */
479 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:*", &set));
480 assert_int_equal(5, set->count);
481
482 ly_set_free(set, NULL);
483
484 /* all top-level nodes from all modules */
485 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/*", &set));
486 assert_int_equal(8, set->count);
487
488 ly_set_free(set, NULL);
489
490 /* all nodes from one module */
491 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//a:*", &set));
492 assert_int_equal(13, set->count);
493
494 ly_set_free(set, NULL);
495
496 /* all nodes from all modules */
497 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//*", &set));
498 assert_int_equal(22, set->count);
499
500 ly_set_free(set, NULL);
501
502 /* all nodes from all modules #2 */
503 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//.", &set));
504 assert_int_equal(22, set->count);
505
506 ly_set_free(set, NULL);
507
508 lyd_free_all(tree);
Michal Vasko61ac2f62020-05-25 12:39:51 +0200509}
510
Michal Vasko519fd602020-05-26 12:17:39 +0200511static void
512test_atomize(void **state)
513{
Michal Vasko519fd602020-05-26 12:17:39 +0200514 struct ly_set *set;
515 const struct lys_module *mod;
516
Radek Iša56ca9e42020-09-08 18:42:00 +0200517 mod = ly_ctx_get_module_latest(UTEST_LYCTX, "a");
518 assert_non_null(mod);
Michal Vasko519fd602020-05-26 12:17:39 +0200519
520 /* some random paths just making sure the API function works */
Michal Vasko400e9672021-01-11 13:39:17 +0100521 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:*", 0, &set));
Michal Vaskoc7304482023-11-30 15:59:30 +0100522 assert_int_equal(7, set->count);
Michal Vasko519fd602020-05-26 12:17:39 +0200523 ly_set_free(set, NULL);
524
525 /* all nodes from all modules (including internal, which can change easily, so check just the test modules) */
Michal Vasko400e9672021-01-11 13:39:17 +0100526 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "//.", 0, &set));
Michal Vasko93923692021-05-07 15:28:02 +0200527 assert_in_range(set->count, 17, UINT32_MAX);
Michal Vasko519fd602020-05-26 12:17:39 +0200528 ly_set_free(set, NULL);
529
Michal Vasko400e9672021-01-11 13:39:17 +0100530 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:c/ll[a='val1']/ll[a='val2']/b", 0, &set));
531 assert_int_equal(6, set->count);
Michal Vasko49fec8e2022-05-24 10:28:33 +0200532 ly_set_free(set, NULL);
Michal Vasko519fd602020-05-26 12:17:39 +0200533
Michal Vaskoa353cce2022-11-14 10:09:55 +0100534 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/ietf-interfaces:interfaces/*", 0, &set));
535 assert_int_equal(2, set->count);
536 ly_set_free(set, NULL);
537
538 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/*", 0, &set));
Michal Vaskoc7304482023-11-30 15:59:30 +0100539 assert_int_equal(14, set->count);
Michal Vaskoa353cce2022-11-14 10:09:55 +0100540 ly_set_free(set, NULL);
541
Michal Vasko49fec8e2022-05-24 10:28:33 +0200542 /*
543 * axes
544 */
545
546 /* ancestor */
547 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "//ll[a and b]/a/ancestor::node()", 0, &set));
548 assert_int_equal(6, set->count);
549 ly_set_free(set, NULL);
550
551 /* ancestor-or-self */
552 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "//ll[a and b]/ancestor-or-self::ll", 0, &set));
553 assert_int_equal(5, set->count);
554 ly_set_free(set, NULL);
555
556 /* attribute */
557 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/l1/attribute::key", 0, &set));
558 assert_int_equal(1, set->count);
559 ly_set_free(set, NULL);
560
561 /* child */
562 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/child::l1/child::a", 0, &set));
563 assert_int_equal(2, set->count);
564 ly_set_free(set, NULL);
565
566 /* descendant */
567 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/descendant::c/descendant::b", 0, &set));
568 assert_int_equal(3, set->count);
569 ly_set_free(set, NULL);
570
571 /* descendant-or-self */
572 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:*/descendant-or-self::c", 0, &set));
Michal Vaskoc7304482023-11-30 15:59:30 +0100573 assert_int_equal(8, set->count);
Michal Vasko49fec8e2022-05-24 10:28:33 +0200574 ly_set_free(set, NULL);
575
576 /* following */
577 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/x/following::a", 0, &set));
578 assert_int_equal(4, set->count);
579 ly_set_free(set, NULL);
580
581 /* following-sibling */
582 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/x/following-sibling::ll", 0, &set));
583 assert_int_equal(3, set->count);
584 ly_set_free(set, NULL);
585
586 /* parent */
587 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/child::a:*/c/parent::l1", 0, &set));
Michal Vaskoc7304482023-11-30 15:59:30 +0100588 assert_int_equal(8, set->count);
Michal Vasko49fec8e2022-05-24 10:28:33 +0200589 ly_set_free(set, NULL);
590
591 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/child::a:c//..", 0, &set));
Michal Vaskoc7304482023-11-30 15:59:30 +0100592 assert_int_equal(11, set->count);
Michal Vasko49fec8e2022-05-24 10:28:33 +0200593 ly_set_free(set, NULL);
594
595 /* preceding */
596 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/preceding::a", 0, &set));
597 assert_int_equal(2, set->count);
598 ly_set_free(set, NULL);
599
600 /* preceding-sibling */
601 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/ll/preceding-sibling::node()", 0, &set));
602 assert_int_equal(3, set->count);
603 ly_set_free(set, NULL);
604
605 /* self */
606 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/c/self::c/ll/ll/b/self::b", 0, &set));
607 assert_int_equal(4, set->count);
Michal Vasko519fd602020-05-26 12:17:39 +0200608 ly_set_free(set, NULL);
609}
610
Michal Vasko4c7763f2020-07-27 17:40:37 +0200611static void
612test_canonize(void **state)
613{
Michal Vasko4c7763f2020-07-27 17:40:37 +0200614 const char *data =
Michal Vasko00099082022-07-28 10:07:41 +0200615 "<foo2 xmlns=\"urn:tests:a\">50</foo2>"
616 "<foo3 xmlns=\"urn:tests:a\" xmlns:a=\"urn:tests:a\">a:id_b</foo3>"
617 "<foo4 xmlns=\"urn:tests:a\">250.5</foo4>";
Michal Vasko4c7763f2020-07-27 17:40:37 +0200618 struct lyd_node *tree;
619 struct ly_set *set;
620
Radek Iša56ca9e42020-09-08 18:42:00 +0200621 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 +0200622 assert_non_null(tree);
623
Michal Vasko00099082022-07-28 10:07:41 +0200624 /* integer */
Michal Vasko4c7763f2020-07-27 17:40:37 +0200625 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo2[.='050']", &set));
626 assert_int_equal(1, set->count);
627 ly_set_free(set, NULL);
628
Michal Vasko00099082022-07-28 10:07:41 +0200629 /* identityref */
630 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo3[.='id_b']", &set));
631 assert_int_equal(1, set->count);
632 ly_set_free(set, NULL);
633
634 /* decimal64 */
635 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo4[.='0250.500']", &set));
636 assert_int_equal(1, set->count);
637 ly_set_free(set, NULL);
Michal Vasko4c7763f2020-07-27 17:40:37 +0200638
639 lyd_free_all(tree);
Michal Vasko4c7763f2020-07-27 17:40:37 +0200640}
641
Michal Vasko93923692021-05-07 15:28:02 +0200642static void
643test_derived_from(void **state)
644{
645 const char *data =
646 "<foo3 xmlns=\"urn:tests:a\">id_c</foo3>";
647 struct lyd_node *tree;
648 struct ly_set *set;
649
650 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
651 assert_non_null(tree);
652
653 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo3[derived-from(., 'a:id_b')]", &set));
654 assert_int_equal(1, set->count);
655 ly_set_free(set, NULL);
656
657 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo3[derived-from(., 'a:id_a')]", &set));
658 assert_int_equal(1, set->count);
659 ly_set_free(set, NULL);
660
661 lyd_free_all(tree);
662}
663
Michal Vaskodb08ce52021-10-06 08:57:49 +0200664static void
665test_augment(void **state)
666{
667 const char *schema_b =
668 "module b {\n"
669 " namespace urn:tests:b;\n"
670 " prefix b;\n"
671 " yang-version 1.1;\n"
672 "\n"
673 " import a {\n"
674 " prefix a;\n"
675 " }\n"
676 "\n"
677 " augment /a:c {\n"
678 " leaf a {\n"
679 " type uint16;\n"
680 " }\n"
681 " }\n"
682 "}";
683 const char *data =
684 "<c xmlns=\"urn:tests:a\">\n"
685 " <x>value</x>\n"
686 " <ll>\n"
687 " <a>key</a>\n"
688 " </ll>\n"
689 " <a xmlns=\"urn:tests:b\">25</a>\n"
690 " <ll2>c1</ll2>\n"
691 "</c>";
692 struct lyd_node *tree;
693 struct ly_set *set;
694
695 UTEST_ADD_MODULE(schema_b, LYS_IN_YANG, NULL, NULL);
696
697 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
698 assert_non_null(tree);
699
700 /* get all children ignoring their module */
701 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/*", &set));
702 assert_int_equal(4, set->count);
703
704 ly_set_free(set, NULL);
705
706 lyd_free_all(tree);
707}
708
aPiecekfba75362021-10-07 12:39:48 +0200709static void
710test_variables(void **state)
711{
712 struct lyd_node *tree, *node;
713 struct ly_set *set;
714 const char *data;
715 struct lyxp_var *vars = NULL;
716
717#define LOCAL_SETUP(DATA, TREE) \
718 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, DATA, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &TREE)); \
719 assert_non_null(TREE);
720
721#define SET_NODE(NODE, SET, INDEX) \
722 assert_non_null(SET); \
723 assert_true(INDEX < SET->count); \
724 NODE = SET->objs[INDEX];
725
726#define LOCAL_TEARDOWN(SET, TREE, VARS) \
727 ly_set_free(SET, NULL); \
728 lyd_free_all(TREE); \
729 lyxp_vars_free(VARS); \
730 vars = NULL;
731
732 /* Eval variable to number. */
733 data =
734 "<l1 xmlns=\"urn:tests:a\">\n"
735 " <a>a1</a>\n"
736 " <b>b1</b>\n"
737 " <c>c1</c>\n"
738 "</l1>"
739 "<l1 xmlns=\"urn:tests:a\">\n"
740 " <a>a2</a>\n"
741 " <b>b2</b>\n"
742 " <c>c2</c>\n"
743 "</l1>";
744 LOCAL_SETUP(data, tree);
745 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "2"));
746 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var]/a", vars, &set));
747 SET_NODE(node, set, 0);
748 assert_string_equal(lyd_get_value(node), "a2");
749 LOCAL_TEARDOWN(set, tree, vars);
750
751 /* Eval variable to string. */
752 data =
753 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
754 LOCAL_SETUP(data, tree);
755 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "\"mstr\""));
756 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/foo[text() = $var]", vars, &set));
757 SET_NODE(node, set, 0);
758 assert_string_equal(lyd_get_value(node), "mstr");
759 LOCAL_TEARDOWN(set, tree, vars);
760
761 /* Eval variable to set of nodes. */
762 data =
763 "<l1 xmlns=\"urn:tests:a\">\n"
764 " <a>a1</a>\n"
765 " <b>b1</b>\n"
766 "</l1>"
767 "<l1 xmlns=\"urn:tests:a\">\n"
768 " <a>a2</a>\n"
769 " <b>b2</b>\n"
770 " <c>c2</c>\n"
771 "</l1>";
772 LOCAL_SETUP(data, tree);
773 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "c"));
774 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var]/a", vars, &set));
775 SET_NODE(node, set, 0);
776 assert_string_equal(lyd_get_value(node), "a2");
777 LOCAL_TEARDOWN(set, tree, vars);
778
779 /* Variable in union expr. */
780 data =
781 "<l1 xmlns=\"urn:tests:a\">\n"
782 " <a>a1</a>\n"
783 " <b>b1</b>\n"
784 " <c>c1</c>\n"
785 "</l1>"
786 "<l1 xmlns=\"urn:tests:a\">\n"
787 " <a>a2</a>\n"
788 " <b>b2</b>\n"
789 " <c>c2</c>\n"
790 "</l1>"
791 "<l1 xmlns=\"urn:tests:a\">\n"
792 " <a>a3</a>\n"
793 " <b>b3</b>\n"
794 " <c>c3</c>\n"
795 "</l1>";
796 LOCAL_SETUP(data, tree);
797 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "c[../a = 'a3']"));
798 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[c[../a = 'a1'] | $var]/a", vars, &set));
799 SET_NODE(node, set, 0);
800 assert_string_equal(lyd_get_value(node), "a1");
801 SET_NODE(node, set, 1);
802 assert_string_equal(lyd_get_value(node), "a3");
803 assert_int_equal(set->count, 2);
804 LOCAL_TEARDOWN(set, tree, vars);
805
806 /* Predicate after variable. */
807 data =
808 "<l1 xmlns=\"urn:tests:a\">\n"
809 " <a>a1</a>\n"
810 " <b>b1</b>\n"
811 " <c>c1</c>\n"
812 "</l1>"
813 "<l1 xmlns=\"urn:tests:a\">\n"
814 " <a>a2</a>\n"
815 " <b>b2</b>\n"
816 " <c>c2</c>\n"
817 "</l1>";
818 LOCAL_SETUP(data, tree);
819 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "c"));
820 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var[../a = 'a1']]/a", vars, &set));
821 SET_NODE(node, set, 0);
822 assert_string_equal(lyd_get_value(node), "a1");
823 LOCAL_TEARDOWN(set, tree, vars);
824
825 /* Variable in variable. */
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, "var1", "$var2"));
830 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var2", "\"mstr\""));
831 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/foo[text() = $var]", vars, &set));
832 SET_NODE(node, set, 0);
833 assert_string_equal(lyd_get_value(node), "mstr");
834 LOCAL_TEARDOWN(set, tree, vars);
835
836 /* Compare two variables. */
837 data =
838 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
839 LOCAL_SETUP(data, tree);
840 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "\"str\""));
841 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var2", "\"str\""));
842 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/foo[$var1 = $var2]", vars, &set));
843 SET_NODE(node, set, 0);
844 assert_string_equal(lyd_get_value(node), "mstr");
845 LOCAL_TEARDOWN(set, tree, vars);
846
847 /* Arithmetic operation with variable. */
848 data =
849 "<foo2 xmlns=\"urn:tests:a\">4</foo2>";
850 LOCAL_SETUP(data, tree);
851 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "2"));
852 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/foo2[.= ($var1 * 2)]", vars, &set));
853 SET_NODE(node, set, 0);
854 assert_string_equal(lyd_get_value(node), "4");
855 LOCAL_TEARDOWN(set, tree, vars);
856
857 /* Variable as function parameter. */
858 data =
859 "<l1 xmlns=\"urn:tests:a\">\n"
860 " <a>a1</a>\n"
861 " <b>b1</b>\n"
862 " <c>c1</c>\n"
863 "</l1>"
864 "<l1 xmlns=\"urn:tests:a\">\n"
865 " <a>a2</a>\n"
866 " <b>b2</b>\n"
867 "</l1>";
868 LOCAL_SETUP(data, tree);
869 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "./c"));
870 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[count($var) = 1]/a", vars, &set));
871 SET_NODE(node, set, 0);
872 assert_string_equal(lyd_get_value(node), "a1");
873 LOCAL_TEARDOWN(set, tree, vars);
874
875 /* Variable in path expr. */
876 /* NOTE: The variable can only be at the beginning of the expression path. */
877 data =
878 "<l1 xmlns=\"urn:tests:a\">\n"
879 " <a>a1</a>\n"
880 " <b>b1</b>\n"
881 " <c>c1</c>\n"
882 "</l1>"
883 "<l1 xmlns=\"urn:tests:a\">\n"
884 " <a>a2</a>\n"
885 " <b>b2</b>\n"
886 "</l1>";
887 LOCAL_SETUP(data, tree);
888 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "/l1"));
889 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var/a]", vars, &set));
890 assert_int_equal(set->count, 2);
891 LOCAL_TEARDOWN(set, tree, vars);
892
893 /* Variable as function. */
894 data =
895 "<l1 xmlns=\"urn:tests:a\">\n"
896 " <a>a1</a>\n"
897 " <b>b1</b>\n"
898 " <c>c1</c>\n"
899 "</l1>"
900 "<l1 xmlns=\"urn:tests:a\">\n"
901 " <a>a2</a>\n"
902 " <b>b2</b>\n"
903 "</l1>";
904 LOCAL_SETUP(data, tree);
905 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "position()"));
906 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var = 2]/a", vars, &set));
907 SET_NODE(node, set, 0);
908 assert_string_equal(lyd_get_value(node), "a2");
909 LOCAL_TEARDOWN(set, tree, vars);
910
911 /* Dynamic change of value. */
912 data =
913 "<l1 xmlns=\"urn:tests:a\">\n"
914 " <a>a1</a>\n"
915 " <b>b1</b>\n"
916 " <c>c1</c>\n"
917 "</l1>"
918 "<l1 xmlns=\"urn:tests:a\">\n"
919 " <a>a2</a>\n"
920 " <b>b2</b>\n"
921 " <c>c2</c>\n"
922 "</l1>";
923 LOCAL_SETUP(data, tree);
924 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "1"));
925 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var]/a", vars, &set));
926 SET_NODE(node, set, 0);
927 assert_string_equal(lyd_get_value(node), "a1");
928 ly_set_free(set, NULL);
929 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "2"));
930 assert_int_equal(LY_SUCCESS, lyd_find_xpath2(tree, "/l1[$var]/a", vars, &set));
931 SET_NODE(node, set, 0);
932 assert_string_equal(lyd_get_value(node), "a2");
933 LOCAL_TEARDOWN(set, tree, vars);
934
935 /* Variable not defined. */
936 data =
937 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
938 LOCAL_SETUP(data, tree);
939 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "\"mstr\""));
940 assert_int_equal(LY_ENOTFOUND, lyd_find_xpath2(tree, "/foo[text() = $var55]", vars, &set));
Michal Vasko7a266772024-01-23 11:02:38 +0100941 CHECK_LOG_CTX("Variable \"var55\" not defined.", NULL, 0);
aPiecekfba75362021-10-07 12:39:48 +0200942 LOCAL_TEARDOWN(set, tree, vars);
943
944 /* Syntax error in value. */
945 data =
946 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
947 LOCAL_SETUP(data, tree);
948 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "\""));
949 assert_int_equal(LY_EVALID, lyd_find_xpath2(tree, "/foo[$var]", vars, &set));
Michal Vasko7a266772024-01-23 11:02:38 +0100950 CHECK_LOG_CTX("Unterminated string delimited with \" (\").", "/a:foo", 0);
aPiecekfba75362021-10-07 12:39:48 +0200951 LOCAL_TEARDOWN(set, tree, vars);
952
953 /* Prefix is not supported. */
954 data =
955 "<foo xmlns=\"urn:tests:a\">mstr</foo>";
956 LOCAL_SETUP(data, tree);
957 assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var", "\""));
958 assert_int_equal(LY_EVALID, lyd_find_xpath2(tree, "/foo[$pref:var]", vars, &set));
Michal Vasko7a266772024-01-23 11:02:38 +0100959 CHECK_LOG_CTX("Variable with prefix is not supported.", NULL, 0);
aPiecekfba75362021-10-07 12:39:48 +0200960 LOCAL_TEARDOWN(set, tree, vars);
961
962#undef LOCAL_SETUP
963#undef LOCAL_TEARDOWN
964}
965
Michal Vasko49fec8e2022-05-24 10:28:33 +0200966static void
967test_axes(void **state)
968{
969 const char *data;
970 struct lyd_node *tree;
971 struct ly_set *set;
972
973 data =
974 "<l1 xmlns=\"urn:tests:a\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\">\n"
975 " <a>a1</a>\n"
976 " <b yang:operation=\"replace\">b1</b>\n"
977 " <c yang:operation=\"none\">c1</c>\n"
978 "</l1>\n"
979 "<l1 xmlns=\"urn:tests:a\">\n"
980 " <a>a2</a>\n"
981 " <b>b2</b>\n"
982 "</l1>"
983 "<l1 xmlns=\"urn:tests:a\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\">\n"
Michal Vasko79a7a872022-06-17 09:00:48 +0200984 " <a yang:operation=\"none\" yang:key=\"[no-key='no-value']\">a3</a>\n"
Michal Vasko49fec8e2022-05-24 10:28:33 +0200985 " <b>b3</b>\n"
986 " <c yang:value=\"no-val\">c3</c>\n"
987 "</l1>"
988 "<c xmlns=\"urn:tests:a\">"
989 " <x>val</x>"
990 " <ll>"
991 " <a>key1</a>"
992 " <ll>"
993 " <a>key11</a>"
994 " <b>val11</b>"
995 " </ll>"
996 " <ll>"
997 " <a>key12</a>"
998 " <b>val12</b>"
999 " </ll>"
1000 " <ll>"
1001 " <a>key13</a>"
1002 " <b>val13</b>"
1003 " </ll>"
1004 " </ll>"
1005 " <ll>"
1006 " <a>key2</a>"
1007 " <ll>"
1008 " <a>key21</a>"
1009 " <b>val21</b>"
1010 " </ll>"
1011 " <ll>"
1012 " <a>key22</a>"
1013 " <b>val22</b>"
1014 " </ll>"
1015 " </ll>"
1016 "</c>";
1017 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
1018 assert_non_null(tree);
1019
1020 /* ancestor */
1021 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//ll[a and b]/a/ancestor::node()", &set));
1022 assert_int_equal(8, set->count);
1023 ly_set_free(set, NULL);
1024
1025 /* ancestor-or-self */
1026 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//ll[a and b]/ancestor-or-self::ll", &set));
1027 assert_int_equal(7, set->count);
1028 ly_set_free(set, NULL);
1029
1030 /* attribute */
1031 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/l1/@operation", &set));
1032 assert_int_equal(0, set->count);
1033 ly_set_free(set, NULL);
1034
1035 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/l1/attribute::key", &set));
1036 assert_int_equal(0, set->count);
1037 ly_set_free(set, NULL);
1038
1039 /* child */
1040 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/child::l1/child::a", &set));
1041 assert_int_equal(3, set->count);
1042 ly_set_free(set, NULL);
1043
1044 /* descendant */
1045 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/descendant::c/descendant::b", &set));
1046 assert_int_equal(5, set->count);
1047 ly_set_free(set, NULL);
1048
1049 /* descendant-or-self */
1050 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//c", &set));
1051 assert_int_equal(3, set->count);
1052 ly_set_free(set, NULL);
1053
1054 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/descendant-or-self::node()/c", &set));
1055 assert_int_equal(3, set->count);
1056 ly_set_free(set, NULL);
1057
1058 /* following */
1059 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/x/following::a", &set));
1060 assert_int_equal(7, set->count);
1061 ly_set_free(set, NULL);
1062
1063 /* following-sibling */
1064 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/x/following-sibling::ll", &set));
1065 assert_int_equal(2, set->count);
1066 ly_set_free(set, NULL);
1067
1068 /* parent */
1069 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/child::*/c/parent::l1", &set));
1070 assert_int_equal(2, set->count);
1071 ly_set_free(set, NULL);
1072
1073 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/child::c//..", &set));
1074 assert_int_equal(8, set->count);
1075 ly_set_free(set, NULL);
1076
1077 /* preceding */
1078 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/preceding::a", &set));
1079 assert_int_equal(3, set->count);
1080 ly_set_free(set, NULL);
1081
1082 /* preceding-sibling */
1083 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/ll/preceding-sibling::node()", &set));
1084 assert_int_equal(2, set->count);
1085 ly_set_free(set, NULL);
1086
1087 /* self */
1088 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/c/self::c/ll/ll/b/self::b", &set));
1089 assert_int_equal(5, set->count);
1090 ly_set_free(set, NULL);
1091
1092 lyd_free_all(tree);
1093}
1094
Michal Vasko99a77882024-01-04 14:50:51 +01001095static void
1096test_trim(void **state)
1097{
1098 const char *data;
1099 char *str1;
1100 struct lyd_node *tree;
1101
1102 data =
1103 "<l1 xmlns=\"urn:tests:a\">"
1104 " <a>a1</a>"
1105 " <b>b1</b>"
1106 " <c>c1</c>"
1107 "</l1>"
1108 "<l1 xmlns=\"urn:tests:a\">"
1109 " <a>a2</a>"
1110 " <b>b2</b>"
1111 "</l1>"
1112 "<l1 xmlns=\"urn:tests:a\">"
1113 " <a>a3</a>"
1114 " <b>b3</b>"
1115 "</l1>"
1116 "<l1 xmlns=\"urn:tests:a\">"
1117 " <a>a4</a>"
1118 " <b>b4</b>"
1119 " <c>c4</c>"
1120 "</l1>"
1121 "<l1 xmlns=\"urn:tests:a\">"
1122 " <a>a5</a>"
1123 " <b>b5</b>"
1124 " <c>c5</c>"
1125 "</l1>"
1126 "<foo2 xmlns=\"urn:tests:a\">50</foo2>"
1127 "<c xmlns=\"urn:tests:a\">"
1128 " <x>key2</x>"
1129 " <ll>"
1130 " <a>key1</a>"
1131 " <ll>"
1132 " <a>key11</a>"
1133 " <b>val11</b>"
1134 " </ll>"
1135 " <ll>"
1136 " <a>key12</a>"
1137 " <b>val12</b>"
1138 " </ll>"
1139 " <ll>"
1140 " <a>key13</a>"
1141 " <b>val13</b>"
1142 " </ll>"
1143 " </ll>"
1144 " <ll>"
1145 " <a>key2</a>"
1146 " <ll>"
1147 " <a>key21</a>"
1148 " <b>val21</b>"
1149 " </ll>"
1150 " <ll>"
1151 " <a>key22</a>"
1152 " <b>val22</b>"
1153 " </ll>"
1154 " </ll>"
1155 " <ll>"
1156 " <a>key3</a>"
1157 " <ll>"
1158 " <a>key31</a>"
1159 " <b>val31</b>"
1160 " </ll>"
1161 " <ll>"
1162 " <a>key32</a>"
1163 " <b>val32</b>"
1164 " </ll>"
1165 " </ll>"
1166 "</c>";
1167
1168 /* trim #1 */
1169 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
1170 assert_non_null(tree);
1171
1172 assert_int_equal(LY_SUCCESS, lyd_trim_xpath(&tree, "/a:c/ll/ll[a='key11']", NULL));
1173 lyd_print_mem(&str1, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS);
1174 assert_string_equal(str1,
1175 "<c xmlns=\"urn:tests:a\">\n"
1176 " <ll>\n"
1177 " <a>key1</a>\n"
1178 " <ll>\n"
1179 " <a>key11</a>\n"
1180 " <b>val11</b>\n"
1181 " </ll>\n"
1182 " </ll>\n"
1183 "</c>\n");
1184
1185 free(str1);
1186 lyd_free_all(tree);
1187
1188 /* trim #2 */
1189 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
1190 assert_non_null(tree);
1191
1192 assert_int_equal(LY_SUCCESS, lyd_trim_xpath(&tree, "/a:c/ll/ll[contains(.,'2')]", NULL));
1193 lyd_print_mem(&str1, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS);
1194 assert_string_equal(str1,
1195 "<c xmlns=\"urn:tests:a\">\n"
1196 " <ll>\n"
1197 " <a>key1</a>\n"
1198 " <ll>\n"
1199 " <a>key12</a>\n"
1200 " <b>val12</b>\n"
1201 " </ll>\n"
1202 " </ll>\n"
1203 " <ll>\n"
1204 " <a>key2</a>\n"
1205 " <ll>\n"
1206 " <a>key21</a>\n"
1207 " <b>val21</b>\n"
1208 " </ll>\n"
1209 " <ll>\n"
1210 " <a>key22</a>\n"
1211 " <b>val22</b>\n"
1212 " </ll>\n"
1213 " </ll>\n"
1214 " <ll>\n"
1215 " <a>key3</a>\n"
1216 " <ll>\n"
1217 " <a>key32</a>\n"
1218 " <b>val32</b>\n"
1219 " </ll>\n"
1220 " </ll>\n"
1221 "</c>\n");
1222
1223 free(str1);
1224 lyd_free_all(tree);
1225
1226 /* trim #3 */
1227 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
1228 assert_non_null(tree);
1229
1230 assert_int_equal(LY_SUCCESS, lyd_trim_xpath(&tree, "/l1[4]//.", NULL));
1231 lyd_print_mem(&str1, tree, LYD_XML, LYD_PRINT_WITHSIBLINGS);
1232 assert_string_equal(str1,
1233 "<l1 xmlns=\"urn:tests:a\">\n"
1234 " <a>a4</a>\n"
1235 " <b>b4</b>\n"
1236 " <c>c4</c>\n"
1237 "</l1>\n");
1238
1239 free(str1);
1240 lyd_free_all(tree);
1241}
1242
Radek Krejcib4ac5a92020-11-23 17:54:33 +01001243int
1244main(void)
Michal Vasko14795a42020-05-22 16:44:44 +02001245{
1246 const struct CMUnitTest tests[] = {
aPiecekfff4dca2021-10-07 10:59:53 +02001247 UTEST(test_predicate, setup),
aPiecekadc1e4f2021-10-07 11:15:12 +02001248 UTEST(test_union, setup),
Michal Vaskoe2be5462021-08-04 10:49:42 +02001249 UTEST(test_invalid, setup),
Radek Iša56ca9e42020-09-08 18:42:00 +02001250 UTEST(test_hash, setup),
Michal Vaskoc7304482023-11-30 15:59:30 +01001251 UTEST(test_rpc, setup),
Radek Iša56ca9e42020-09-08 18:42:00 +02001252 UTEST(test_toplevel, setup),
1253 UTEST(test_atomize, setup),
1254 UTEST(test_canonize, setup),
Michal Vasko93923692021-05-07 15:28:02 +02001255 UTEST(test_derived_from, setup),
Michal Vaskodb08ce52021-10-06 08:57:49 +02001256 UTEST(test_augment, setup),
aPiecekfba75362021-10-07 12:39:48 +02001257 UTEST(test_variables, setup),
Michal Vasko49fec8e2022-05-24 10:28:33 +02001258 UTEST(test_axes, setup),
Michal Vasko99a77882024-01-04 14:50:51 +01001259 UTEST(test_trim, setup),
Michal Vasko14795a42020-05-22 16:44:44 +02001260 };
1261
1262 return cmocka_run_group_tests(tests, NULL, NULL);
1263}