blob: b5c3f4c9a52f6983b5166dd063ab036da645868d [file] [log] [blame]
Radek Krejci509e2592019-05-15 16:30:48 +02001/*
2 * @file test_parser_xml.c
3 * @author: Radek Krejci <rkrejci@cesnet.cz>
4 * @brief unit tests for functions from parser_xml.c
5 *
6 * Copyright (c) 2019 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 */
14
Radek Krejci509e2592019-05-15 16:30:48 +020015#include <stdarg.h>
16#include <stddef.h>
17#include <setjmp.h>
18#include <cmocka.h>
19
20#include <stdio.h>
21#include <string.h>
22
Michal Vasko8d544252020-03-02 10:19:52 +010023#include "tests/config.h"
24
Radek Krejci2d7a47b2019-05-16 13:34:10 +020025#include "../../src/context.h"
26#include "../../src/tree_data_internal.h"
Radek Krejci509e2592019-05-15 16:30:48 +020027
28#define BUFSIZE 1024
29char logbuf[BUFSIZE] = {0};
30int store = -1; /* negative for infinite logging, positive for limited logging */
31
32struct ly_ctx *ctx; /* context for tests */
33
34/* set to 0 to printing error messages to stderr instead of checking them in code */
35#define ENABLE_LOGGER_CHECKING 1
36
37#if ENABLE_LOGGER_CHECKING
38static void
39logger(LY_LOG_LEVEL level, const char *msg, const char *path)
40{
41 (void) level; /* unused */
42 if (store) {
43 if (path && path[0]) {
44 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
45 } else {
46 strncpy(logbuf, msg, BUFSIZE - 1);
47 }
48 if (store > 0) {
49 --store;
50 }
51 }
52}
53#endif
54
55static int
56setup(void **state)
57{
58 (void) state; /* unused */
59
60 const char *schema_a = "module a {namespace urn:tests:a;prefix a;yang-version 1.1;"
Radek Krejci710226d2019-07-24 17:24:59 +020061 "list l1 { key \"a b c\"; leaf a {type string;} leaf b {type string;} leaf c {type string;} leaf d {type string;}}"
Radek Krejciee4cab22019-07-17 17:07:47 +020062 "leaf foo { type string;}"
Radek Krejcib6f7ae52019-07-19 10:31:42 +020063 "container c { leaf x {type string;}}"
64 "container cp {presence \"container switch\"; leaf y {type string;}}"
Michal Vasko8d544252020-03-02 10:19:52 +010065 "anydata any {config false;}"
66 "leaf foo2 { type string; default \"default-val\"; }}";
Radek Krejci509e2592019-05-15 16:30:48 +020067
68#if ENABLE_LOGGER_CHECKING
69 ly_set_log_clb(logger, 1);
70#endif
71
Michal Vasko8d544252020-03-02 10:19:52 +010072 assert_int_equal(LY_SUCCESS, ly_ctx_new(TESTS_DIR_MODULES_YANG, 0, &ctx));
73 assert_non_null(ly_ctx_load_module(ctx, "ietf-netconf-with-defaults", "2011-06-01"));
Radek Krejci509e2592019-05-15 16:30:48 +020074 assert_non_null(lys_parse_mem(ctx, schema_a, LYS_IN_YANG));
75
76 return 0;
77}
78
79static int
80teardown(void **state)
81{
82#if ENABLE_LOGGER_CHECKING
83 if (*state) {
84 fprintf(stderr, "%s\n", logbuf);
85 }
86#else
87 (void) state; /* unused */
88#endif
89
90 ly_ctx_destroy(ctx, NULL);
91 ctx = NULL;
92
93 return 0;
94}
95
96void
97logbuf_clean(void)
98{
99 logbuf[0] = '\0';
100}
101
102#if ENABLE_LOGGER_CHECKING
103# define logbuf_assert(str) assert_string_equal(logbuf, str)
104#else
105# define logbuf_assert(str)
106#endif
107
Radek Krejci509e2592019-05-15 16:30:48 +0200108static void
109test_leaf(void **state)
110{
111 *state = test_leaf;
112
113 const char *data = "<foo xmlns=\"urn:tests:a\">foo value</foo>";
114 struct lyd_node *tree;
115 struct lyd_node_term *leaf;
116
Michal Vasko9f96a052020-03-10 09:41:45 +0100117 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejci509e2592019-05-15 16:30:48 +0200118 assert_non_null(tree);
119 assert_int_equal(LYS_LEAF, tree->schema->nodetype);
120 assert_string_equal("foo", tree->schema->name);
121 leaf = (struct lyd_node_term*)tree;
Radek Krejci950f6a52019-09-12 17:15:32 +0200122 assert_string_equal("foo value", leaf->value.original);
Radek Krejci509e2592019-05-15 16:30:48 +0200123
Michal Vasko8d544252020-03-02 10:19:52 +0100124 assert_int_equal(LYS_LEAF, tree->next->next->schema->nodetype);
125 assert_string_equal("foo2", tree->next->next->schema->name);
126 leaf = (struct lyd_node_term*)tree->next->next;
127 assert_string_equal("default-val", leaf->value.original);
128 assert_true(leaf->flags & LYD_DEFAULT);
129
Radek Krejci509e2592019-05-15 16:30:48 +0200130 lyd_free_all(tree);
Michal Vasko8d544252020-03-02 10:19:52 +0100131
132 /* make foo2 explicit */
133 data = "<foo2 xmlns=\"urn:tests:a\">default-val</foo2>";
Michal Vasko9f96a052020-03-10 09:41:45 +0100134 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Michal Vasko8d544252020-03-02 10:19:52 +0100135 assert_non_null(tree);
136 assert_int_equal(LYS_LEAF, tree->schema->nodetype);
137 assert_string_equal("foo2", tree->schema->name);
138 leaf = (struct lyd_node_term*)tree;
139 assert_string_equal("default-val", leaf->value.original);
140 assert_false(leaf->flags & LYD_DEFAULT);
141
142 lyd_free_all(tree);
143
144 /* parse foo2 but make it implicit */
145 data = "<foo2 xmlns=\"urn:tests:a\" xmlns:wd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\" wd:default=\"true\">default-val</foo2>";
Michal Vasko9f96a052020-03-10 09:41:45 +0100146 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Michal Vasko8d544252020-03-02 10:19:52 +0100147 assert_non_null(tree);
148 assert_int_equal(LYS_LEAF, tree->schema->nodetype);
149 assert_string_equal("foo2", tree->schema->name);
150 leaf = (struct lyd_node_term*)tree;
151 assert_string_equal("default-val", leaf->value.original);
152 assert_true(leaf->flags & LYD_DEFAULT);
153
154 lyd_free_all(tree);
155
Radek Krejci509e2592019-05-15 16:30:48 +0200156 *state = NULL;
157}
158
Radek Krejciee4cab22019-07-17 17:07:47 +0200159static void
160test_anydata(void **state)
161{
162 *state = test_anydata;
163
164 const char *data = "<any xmlns=\"urn:tests:a\">"
165 "<element1><x:element2 x:attr2=\"test\" xmlns:x=\"urn:x\">x:data</x:element2></element1><element1a/>"
166 "</any>";
167 struct lyd_node *tree;
168 struct lyd_node_any *any;
169
Michal Vasko9f96a052020-03-10 09:41:45 +0100170 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejciee4cab22019-07-17 17:07:47 +0200171 assert_non_null(tree);
172 assert_int_equal(LYS_ANYDATA, tree->schema->nodetype);
173 assert_string_equal("any", tree->schema->name);
174 any = (struct lyd_node_any*)tree;
175 assert_int_equal(LYD_ANYDATA_XML, any->value_type);
176 assert_string_equal("<element1><x:element2 x:attr2=\"test\" xmlns:x=\"urn:x\">x:data</x:element2></element1><element1a/>", any->value.xml);
177
178 lyd_free_all(tree);
179 *state = NULL;
180}
181
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200182static void
183test_list(void **state)
184{
185 *state = test_list;
186
187 const char *data = "<l1 xmlns=\"urn:tests:a\"><a>one</a><b>one</b><c>one</c></l1>";
188 struct lyd_node *tree, *iter;
189 struct lyd_node_inner *list;
Radek Krejci710226d2019-07-24 17:24:59 +0200190 struct lyd_node_term *leaf;
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200191
Radek Krejci710226d2019-07-24 17:24:59 +0200192 /* check hashes */
Michal Vasko9f96a052020-03-10 09:41:45 +0100193 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200194 assert_non_null(tree);
195 assert_int_equal(LYS_LIST, tree->schema->nodetype);
196 assert_string_equal("l1", tree->schema->name);
197 list = (struct lyd_node_inner*)tree;
198 LY_LIST_FOR(list->child, iter) {
199 assert_int_not_equal(0, iter->hash);
200 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200201 lyd_free_all(tree);
Radek Krejci710226d2019-07-24 17:24:59 +0200202
Michal Vasko9f96a052020-03-10 09:41:45 +0100203 /* missing keys */
204 data = "<l1 xmlns=\"urn:tests:a\"><c>c</c><b>b</b></l1>";
205 assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
206 logbuf_assert("List instance is missing its key \"a\". /a:l1[b='b'][c='c']");
207
208 data = "<l1 xmlns=\"urn:tests:a\"><a>a</a></l1>";
209 assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
210 logbuf_assert("List instance is missing its key \"b\". /a:l1[a='a']");
211
212 data = "<l1 xmlns=\"urn:tests:a\"><b>b</b><a>a</a></l1>";
213 assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
214 logbuf_assert("List instance is missing its key \"c\". /a:l1[a='a'][b='b']");
215
216 /* key duplicate */
217 data = "<l1 xmlns=\"urn:tests:a\"><c>c</c><b>b</b><a>a</a><c>d</c></l1>";
218 assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
219 logbuf_assert("Duplicate instance of \"c\". /a:l1[a='a'][b='b'][c='d'][c='c']/c");
220
Radek Krejci710226d2019-07-24 17:24:59 +0200221 /* keys order */
222 data = "<l1 xmlns=\"urn:tests:a\"><d>d</d><a>a</a><c>c</c><b>b</b></l1>";
Michal Vasko9f96a052020-03-10 09:41:45 +0100223 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejci710226d2019-07-24 17:24:59 +0200224 assert_non_null(tree);
225 assert_int_equal(LYS_LIST, tree->schema->nodetype);
226 assert_string_equal("l1", tree->schema->name);
227 list = (struct lyd_node_inner*)tree;
228 assert_non_null(leaf = (struct lyd_node_term*)list->child);
229 assert_string_equal("a", leaf->schema->name);
230 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
231 assert_string_equal("b", leaf->schema->name);
232 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
233 assert_string_equal("c", leaf->schema->name);
234 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
235 assert_string_equal("d", leaf->schema->name);
236 logbuf_assert("Invalid position of the key \"b\" in a list.");
237 lyd_free_all(tree);
238
239 data = "<l1 xmlns=\"urn:tests:a\"><c>c</c><b>b</b><a>a</a></l1>";
Michal Vasko9f96a052020-03-10 09:41:45 +0100240 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejci710226d2019-07-24 17:24:59 +0200241 assert_non_null(tree);
242 assert_int_equal(LYS_LIST, tree->schema->nodetype);
243 assert_string_equal("l1", tree->schema->name);
244 list = (struct lyd_node_inner*)tree;
245 assert_non_null(leaf = (struct lyd_node_term*)list->child);
246 assert_string_equal("a", leaf->schema->name);
247 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
248 assert_string_equal("b", leaf->schema->name);
249 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
250 assert_string_equal("c", leaf->schema->name);
251 logbuf_assert("Invalid position of the key \"a\" in a list.");
252 logbuf_clean();
253 lyd_free_all(tree);
254
Michal Vasko9f96a052020-03-10 09:41:45 +0100255 assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_OPT_STRICT, &tree));
Radek Krejci710226d2019-07-24 17:24:59 +0200256 logbuf_assert("Invalid position of the key \"b\" in a list. Line number 1.");
257
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200258 *state = NULL;
259}
260
Radek Krejcib6f7ae52019-07-19 10:31:42 +0200261static void
262test_container(void **state)
263{
264 *state = test_container;
265
266 const char *data = "<c xmlns=\"urn:tests:a\"/>";
267 struct lyd_node *tree;
268 struct lyd_node_inner *cont;
269
Michal Vasko9f96a052020-03-10 09:41:45 +0100270 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejcib6f7ae52019-07-19 10:31:42 +0200271 assert_non_null(tree);
272 assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
273 assert_string_equal("c", tree->schema->name);
274 cont = (struct lyd_node_inner*)tree;
275 assert_true(cont->flags & LYD_DEFAULT);
276 lyd_free_all(tree);
277
278 data = "<cp xmlns=\"urn:tests:a\"/>";
Michal Vasko9f96a052020-03-10 09:41:45 +0100279 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejcib6f7ae52019-07-19 10:31:42 +0200280 assert_non_null(tree);
281 assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
282 assert_string_equal("cp", tree->schema->name);
283 cont = (struct lyd_node_inner*)tree;
284 assert_false(cont->flags & LYD_DEFAULT);
285 lyd_free_all(tree);
286
287 *state = NULL;
288}
289
Radek Krejci509e2592019-05-15 16:30:48 +0200290int main(void)
291{
292 const struct CMUnitTest tests[] = {
293 cmocka_unit_test_setup_teardown(test_leaf, setup, teardown),
Radek Krejciee4cab22019-07-17 17:07:47 +0200294 cmocka_unit_test_setup_teardown(test_anydata, setup, teardown),
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200295 cmocka_unit_test_setup_teardown(test_list, setup, teardown),
Radek Krejcib6f7ae52019-07-19 10:31:42 +0200296 cmocka_unit_test_setup_teardown(test_container, setup, teardown),
Radek Krejci509e2592019-05-15 16:30:48 +0200297 };
298
299 return cmocka_run_group_tests(tests, NULL, NULL);
300}