blob: 889874b3175bba5b29b3d95b0a675e4f17d18afd [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
99test_hash(void **state)
100{
Michal Vasko14795a42020-05-22 16:44:44 +0200101 const char *data =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100102 "<l1 xmlns=\"urn:tests:a\">\n"
103 " <a>a1</a>\n"
104 " <b>b1</b>\n"
105 " <c>c1</c>\n"
106 "</l1>\n"
107 "<l1 xmlns=\"urn:tests:a\">\n"
108 " <a>a2</a>\n"
109 " <b>b2</b>\n"
110 "</l1>\n"
111 "<l1 xmlns=\"urn:tests:a\">\n"
112 " <a>a3</a>\n"
113 " <b>b3</b>\n"
114 " <c>c3</c>\n"
115 "</l1>\n"
116 "<foo xmlns=\"urn:tests:a\">foo value</foo>\n"
117 "<c xmlns=\"urn:tests:a\">\n"
118 " <x>val</x>\n"
119 " <ll>\n"
120 " <a>val_a</a>\n"
121 " <ll>\n"
122 " <a>val_a</a>\n"
123 " <b>val</b>\n"
124 " </ll>\n"
125 " <ll>\n"
126 " <a>val_b</a>\n"
127 " </ll>\n"
128 " </ll>\n"
129 " <ll>\n"
130 " <a>val_b</a>\n"
131 " <ll>\n"
132 " <a>val_a</a>\n"
133 " </ll>\n"
134 " <ll>\n"
135 " <a>val_b</a>\n"
136 " <b>val</b>\n"
137 " </ll>\n"
138 " </ll>\n"
139 " <ll>\n"
140 " <a>val_c</a>\n"
141 " <ll>\n"
142 " <a>val_a</a>\n"
143 " </ll>\n"
144 " <ll>\n"
145 " <a>val_b</a>\n"
146 " </ll>\n"
147 " </ll>\n"
148 " <ll2>one</ll2>\n"
149 " <ll2>two</ll2>\n"
150 " <ll2>three</ll2>\n"
151 " <ll2>four</ll2>\n"
152 "</c>";
Michal Vasko14795a42020-05-22 16:44:44 +0200153 struct lyd_node *tree, *node;
154 struct ly_set *set;
Michal Vasko14795a42020-05-22 16:44:44 +0200155
Radek Iša56ca9e42020-09-08 18:42:00 +0200156 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 +0200157 assert_non_null(tree);
158
159 /* top-level, so hash table is not ultimately used but instances can be compared based on hashes */
160 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:l1[a='a3'][b='b3']", &set));
161 assert_int_equal(1, set->count);
162
163 node = set->objs[0];
164 assert_string_equal(node->schema->name, "l1");
Radek Krejcia1c1e542020-09-29 16:06:52 +0200165 node = lyd_child(node);
Michal Vasko14795a42020-05-22 16:44:44 +0200166 assert_string_equal(node->schema->name, "a");
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200167 assert_string_equal(lyd_get_value(node), "a3");
Michal Vasko14795a42020-05-22 16:44:44 +0200168
169 ly_set_free(set, NULL);
170
171 /* hashes should be used for both searches (well, there are not enough nested ll instances, so technically not true) */
172 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[a='val_b']/ll[a='val_b']", &set));
173 assert_int_equal(1, set->count);
174
175 node = set->objs[0];
176 assert_string_equal(node->schema->name, "ll");
Radek Krejcia1c1e542020-09-29 16:06:52 +0200177 node = lyd_child(node);
Michal Vasko14795a42020-05-22 16:44:44 +0200178 assert_string_equal(node->schema->name, "a");
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200179 assert_string_equal(lyd_get_value(node), "val_b");
Michal Vasko14795a42020-05-22 16:44:44 +0200180 node = node->next;
181 assert_string_equal(node->schema->name, "b");
182 assert_null(node->next);
183
184 ly_set_free(set, NULL);
185
186 /* hashes are not used */
187 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c//ll[a='val_b']", &set));
188 assert_int_equal(4, set->count);
189
190 ly_set_free(set, NULL);
191
Michal Vasko660cc8f2020-05-25 10:33:19 +0200192 /* hashes used even for leaf-lists */
193 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll2[. = 'three']", &set));
194 assert_int_equal(1, set->count);
195
196 node = set->objs[0];
197 assert_string_equal(node->schema->name, "ll2");
Radek Krejci6d5ba0c2021-04-26 07:49:59 +0200198 assert_string_equal(lyd_get_value(node), "three");
Michal Vasko660cc8f2020-05-25 10:33:19 +0200199
200 ly_set_free(set, NULL);
201
Michal Vasko14795a42020-05-22 16:44:44 +0200202 /* not found using hashes */
203 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[a='val_d']", &set));
204 assert_int_equal(0, set->count);
205
206 ly_set_free(set, NULL);
207
208 /* white-spaces are also ok */
209 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:c/ll[ \na = 'val_c' ]", &set));
210 assert_int_equal(1, set->count);
211
212 ly_set_free(set, NULL);
213
214 lyd_free_all(tree);
Michal Vasko14795a42020-05-22 16:44:44 +0200215}
216
Michal Vasko61ac2f62020-05-25 12:39:51 +0200217static void
218test_toplevel(void **state)
219{
Radek Iša56ca9e42020-09-08 18:42:00 +0200220 const char *schema_b =
221 "module b {\n"
222 " namespace urn:tests:b;\n"
223 " prefix b;\n"
224 " yang-version 1.1;\n"
225 "\n"
226 " list l2 {\n"
227 " key \"a\";\n"
228 " leaf a {\n"
229 " type uint16;\n"
230 " }\n"
231 " leaf b {\n"
232 " type uint16;\n"
233 " }\n"
234 " }\n"
235 "}";
Michal Vasko61ac2f62020-05-25 12:39:51 +0200236 const char *data =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100237 "<l1 xmlns=\"urn:tests:a\">\n"
238 " <a>a1</a>\n"
239 " <b>b1</b>\n"
240 " <c>c1</c>\n"
241 "</l1>\n"
242 "<l1 xmlns=\"urn:tests:a\">\n"
243 " <a>a2</a>\n"
244 " <b>b2</b>\n"
245 "</l1>\n"
246 "<l1 xmlns=\"urn:tests:a\">\n"
247 " <a>a3</a>\n"
248 " <b>b3</b>\n"
249 " <c>c3</c>\n"
250 "</l1>\n"
251 "<foo xmlns=\"urn:tests:a\">foo value</foo>\n"
252 "<l2 xmlns=\"urn:tests:b\">\n"
253 " <a>1</a>\n"
254 " <b>1</b>\n"
255 "</l2>\n"
256 "<l2 xmlns=\"urn:tests:b\">\n"
257 " <a>2</a>\n"
258 " <b>1</b>\n"
259 "</l2>\n"
260 "<l2 xmlns=\"urn:tests:b\">\n"
261 " <a>3</a>\n"
262 " <b>1</b>\n"
263 "</l2>";
Michal Vaskof60e7102020-05-26 10:48:59 +0200264 struct lyd_node *tree;
Michal Vasko61ac2f62020-05-25 12:39:51 +0200265 struct ly_set *set;
Michal Vasko61ac2f62020-05-25 12:39:51 +0200266
Radek Iša56ca9e42020-09-08 18:42:00 +0200267 UTEST_ADD_MODULE(schema_b, LYS_IN_YANG, NULL, NULL);
268
269 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 +0200270 assert_non_null(tree);
271
272 /* all top-level nodes from one module (default container as well) */
273 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:*", &set));
274 assert_int_equal(5, set->count);
275
276 ly_set_free(set, NULL);
277
278 /* all top-level nodes from all modules */
279 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/*", &set));
280 assert_int_equal(8, set->count);
281
282 ly_set_free(set, NULL);
283
284 /* all nodes from one module */
285 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//a:*", &set));
286 assert_int_equal(13, set->count);
287
288 ly_set_free(set, NULL);
289
290 /* all nodes from all modules */
291 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//*", &set));
292 assert_int_equal(22, set->count);
293
294 ly_set_free(set, NULL);
295
296 /* all nodes from all modules #2 */
297 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "//.", &set));
298 assert_int_equal(22, set->count);
299
300 ly_set_free(set, NULL);
301
302 lyd_free_all(tree);
Michal Vasko61ac2f62020-05-25 12:39:51 +0200303}
304
Michal Vasko519fd602020-05-26 12:17:39 +0200305static void
306test_atomize(void **state)
307{
Michal Vasko519fd602020-05-26 12:17:39 +0200308 struct ly_set *set;
309 const struct lys_module *mod;
310
Radek Iša56ca9e42020-09-08 18:42:00 +0200311 mod = ly_ctx_get_module_latest(UTEST_LYCTX, "a");
312 assert_non_null(mod);
Michal Vasko519fd602020-05-26 12:17:39 +0200313
314 /* some random paths just making sure the API function works */
Michal Vasko400e9672021-01-11 13:39:17 +0100315 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:*", 0, &set));
Michal Vasko93923692021-05-07 15:28:02 +0200316 assert_int_equal(5, set->count);
Michal Vasko519fd602020-05-26 12:17:39 +0200317
318 ly_set_free(set, NULL);
319
320 /* all nodes from all modules (including internal, which can change easily, so check just the test modules) */
Michal Vasko400e9672021-01-11 13:39:17 +0100321 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "//.", 0, &set));
Michal Vasko93923692021-05-07 15:28:02 +0200322 assert_in_range(set->count, 17, UINT32_MAX);
Michal Vasko519fd602020-05-26 12:17:39 +0200323
324 ly_set_free(set, NULL);
325
Michal Vasko400e9672021-01-11 13:39:17 +0100326 assert_int_equal(LY_SUCCESS, lys_find_xpath_atoms(UTEST_LYCTX, NULL, "/a:c/ll[a='val1']/ll[a='val2']/b", 0, &set));
327 assert_int_equal(6, set->count);
Michal Vasko519fd602020-05-26 12:17:39 +0200328
329 ly_set_free(set, NULL);
330}
331
Michal Vasko4c7763f2020-07-27 17:40:37 +0200332static void
333test_canonize(void **state)
334{
Michal Vasko4c7763f2020-07-27 17:40:37 +0200335 const char *data =
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100336 "<foo2 xmlns=\"urn:tests:a\">50</foo2>";
Michal Vasko4c7763f2020-07-27 17:40:37 +0200337 struct lyd_node *tree;
338 struct ly_set *set;
339
Radek Iša56ca9e42020-09-08 18:42:00 +0200340 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 +0200341 assert_non_null(tree);
342
343 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo2[.='050']", &set));
344 assert_int_equal(1, set->count);
345 ly_set_free(set, NULL);
346
347 /* TODO more use-cases once there are some type plugins that have canonical values */
348
349 lyd_free_all(tree);
Michal Vasko4c7763f2020-07-27 17:40:37 +0200350}
351
Michal Vasko93923692021-05-07 15:28:02 +0200352static void
353test_derived_from(void **state)
354{
355 const char *data =
356 "<foo3 xmlns=\"urn:tests:a\">id_c</foo3>";
357 struct lyd_node *tree;
358 struct ly_set *set;
359
360 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
361 assert_non_null(tree);
362
363 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo3[derived-from(., 'a:id_b')]", &set));
364 assert_int_equal(1, set->count);
365 ly_set_free(set, NULL);
366
367 assert_int_equal(LY_SUCCESS, lyd_find_xpath(tree, "/a:foo3[derived-from(., 'a:id_a')]", &set));
368 assert_int_equal(1, set->count);
369 ly_set_free(set, NULL);
370
371 lyd_free_all(tree);
372}
373
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100374int
375main(void)
Michal Vasko14795a42020-05-22 16:44:44 +0200376{
377 const struct CMUnitTest tests[] = {
Radek Iša56ca9e42020-09-08 18:42:00 +0200378 UTEST(test_hash, setup),
379 UTEST(test_toplevel, setup),
380 UTEST(test_atomize, setup),
381 UTEST(test_canonize, setup),
Michal Vasko93923692021-05-07 15:28:02 +0200382 UTEST(test_derived_from, setup),
Michal Vasko14795a42020-05-22 16:44:44 +0200383 };
384
385 return cmocka_run_group_tests(tests, NULL, NULL);
386}