blob: 247ff0afc486783c7ef1babdacb866f94fa32b83 [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
Michal Vasko52927e22020-03-16 17:26:14 +010015#include "tests/config.h"
16
Radek Krejci509e2592019-05-15 16:30:48 +020017#include <stdarg.h>
18#include <stddef.h>
19#include <setjmp.h>
20#include <cmocka.h>
21
22#include <stdio.h>
23#include <string.h>
24
Radek Krejci2d7a47b2019-05-16 13:34:10 +020025#include "../../src/context.h"
26#include "../../src/tree_data_internal.h"
Michal Vasko52927e22020-03-16 17:26:14 +010027#include "../../src/printer_data.h"
Radek Krejci509e2592019-05-15 16:30:48 +020028
29#define BUFSIZE 1024
30char logbuf[BUFSIZE] = {0};
31int store = -1; /* negative for infinite logging, positive for limited logging */
32
33struct ly_ctx *ctx; /* context for tests */
34
35/* set to 0 to printing error messages to stderr instead of checking them in code */
36#define ENABLE_LOGGER_CHECKING 1
37
38#if ENABLE_LOGGER_CHECKING
39static void
40logger(LY_LOG_LEVEL level, const char *msg, const char *path)
41{
42 (void) level; /* unused */
43 if (store) {
44 if (path && path[0]) {
45 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
46 } else {
47 strncpy(logbuf, msg, BUFSIZE - 1);
48 }
49 if (store > 0) {
50 --store;
51 }
52 }
53}
54#endif
55
56static int
57setup(void **state)
58{
59 (void) state; /* unused */
60
61 const char *schema_a = "module a {namespace urn:tests:a;prefix a;yang-version 1.1;"
Radek Krejci710226d2019-07-24 17:24:59 +020062 "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 +020063 "leaf foo { type string;}"
Radek Krejcib6f7ae52019-07-19 10:31:42 +020064 "container c { leaf x {type string;}}"
65 "container cp {presence \"container switch\"; leaf y {type string;}}"
Michal Vasko8d544252020-03-02 10:19:52 +010066 "anydata any {config false;}"
67 "leaf foo2 { type string; default \"default-val\"; }}";
Radek Krejci509e2592019-05-15 16:30:48 +020068
69#if ENABLE_LOGGER_CHECKING
70 ly_set_log_clb(logger, 1);
71#endif
72
Michal Vasko8d544252020-03-02 10:19:52 +010073 assert_int_equal(LY_SUCCESS, ly_ctx_new(TESTS_DIR_MODULES_YANG, 0, &ctx));
74 assert_non_null(ly_ctx_load_module(ctx, "ietf-netconf-with-defaults", "2011-06-01"));
Radek Krejci509e2592019-05-15 16:30:48 +020075 assert_non_null(lys_parse_mem(ctx, schema_a, LYS_IN_YANG));
76
77 return 0;
78}
79
80static int
81teardown(void **state)
82{
83#if ENABLE_LOGGER_CHECKING
84 if (*state) {
85 fprintf(stderr, "%s\n", logbuf);
86 }
87#else
88 (void) state; /* unused */
89#endif
90
91 ly_ctx_destroy(ctx, NULL);
92 ctx = NULL;
93
94 return 0;
95}
96
97void
98logbuf_clean(void)
99{
100 logbuf[0] = '\0';
101}
102
103#if ENABLE_LOGGER_CHECKING
104# define logbuf_assert(str) assert_string_equal(logbuf, str)
105#else
106# define logbuf_assert(str)
107#endif
108
Radek Krejci509e2592019-05-15 16:30:48 +0200109static void
110test_leaf(void **state)
111{
112 *state = test_leaf;
113
114 const char *data = "<foo xmlns=\"urn:tests:a\">foo value</foo>";
115 struct lyd_node *tree;
116 struct lyd_node_term *leaf;
117
Michal Vasko9f96a052020-03-10 09:41:45 +0100118 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejci509e2592019-05-15 16:30:48 +0200119 assert_non_null(tree);
120 assert_int_equal(LYS_LEAF, tree->schema->nodetype);
121 assert_string_equal("foo", tree->schema->name);
122 leaf = (struct lyd_node_term*)tree;
Radek Krejci950f6a52019-09-12 17:15:32 +0200123 assert_string_equal("foo value", leaf->value.original);
Radek Krejci509e2592019-05-15 16:30:48 +0200124
Michal Vasko8d544252020-03-02 10:19:52 +0100125 assert_int_equal(LYS_LEAF, tree->next->next->schema->nodetype);
126 assert_string_equal("foo2", tree->next->next->schema->name);
127 leaf = (struct lyd_node_term*)tree->next->next;
128 assert_string_equal("default-val", leaf->value.original);
129 assert_true(leaf->flags & LYD_DEFAULT);
130
Radek Krejci509e2592019-05-15 16:30:48 +0200131 lyd_free_all(tree);
Michal Vasko8d544252020-03-02 10:19:52 +0100132
133 /* make foo2 explicit */
134 data = "<foo2 xmlns=\"urn:tests:a\">default-val</foo2>";
Michal Vasko9f96a052020-03-10 09:41:45 +0100135 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Michal Vasko8d544252020-03-02 10:19:52 +0100136 assert_non_null(tree);
137 assert_int_equal(LYS_LEAF, tree->schema->nodetype);
138 assert_string_equal("foo2", tree->schema->name);
139 leaf = (struct lyd_node_term*)tree;
140 assert_string_equal("default-val", leaf->value.original);
141 assert_false(leaf->flags & LYD_DEFAULT);
142
143 lyd_free_all(tree);
144
145 /* parse foo2 but make it implicit */
146 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 +0100147 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Michal Vasko8d544252020-03-02 10:19:52 +0100148 assert_non_null(tree);
149 assert_int_equal(LYS_LEAF, tree->schema->nodetype);
150 assert_string_equal("foo2", tree->schema->name);
151 leaf = (struct lyd_node_term*)tree;
152 assert_string_equal("default-val", leaf->value.original);
153 assert_true(leaf->flags & LYD_DEFAULT);
154
155 lyd_free_all(tree);
156
Radek Krejci509e2592019-05-15 16:30:48 +0200157 *state = NULL;
158}
159
Radek Krejciee4cab22019-07-17 17:07:47 +0200160static void
161test_anydata(void **state)
162{
163 *state = test_anydata;
164
Michal Vasko52927e22020-03-16 17:26:14 +0100165 const char *data;
166 char *str;
Radek Krejciee4cab22019-07-17 17:07:47 +0200167 struct lyd_node *tree;
Radek Krejciee4cab22019-07-17 17:07:47 +0200168
Michal Vasko52927e22020-03-16 17:26:14 +0100169 data =
170 "<any xmlns=\"urn:tests:a\">"
171 "<element1>"
172 "<x:element2 x:attr2=\"test\" xmlns:a=\"urn:tests:a\" xmlns:x=\"urn:x\">a:data</x:element2>"
173 "</element1>"
174 "<element1a/>"
175 "</any>";
Michal Vasko9f96a052020-03-10 09:41:45 +0100176 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejciee4cab22019-07-17 17:07:47 +0200177 assert_non_null(tree);
178 assert_int_equal(LYS_ANYDATA, tree->schema->nodetype);
179 assert_string_equal("any", tree->schema->name);
Michal Vasko52927e22020-03-16 17:26:14 +0100180
181 lyd_print_mem(&str, tree, LYD_XML, 0);
182 assert_string_equal(str,
183 "<any xmlns=\"urn:tests:a\">"
184 "<element1>"
185 "<element2 xmlns=\"urn:x\" xmlns:x=\"urn:x\" x:attr2=\"test\" xmlns:a=\"urn:tests:a\">a:data</element2>"
186 "</element1>"
187 "<element1a/>"
188 "</any>"
189 );
190 free(str);
Radek Krejciee4cab22019-07-17 17:07:47 +0200191
192 lyd_free_all(tree);
193 *state = NULL;
194}
195
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200196static void
197test_list(void **state)
198{
199 *state = test_list;
200
201 const char *data = "<l1 xmlns=\"urn:tests:a\"><a>one</a><b>one</b><c>one</c></l1>";
202 struct lyd_node *tree, *iter;
203 struct lyd_node_inner *list;
Radek Krejci710226d2019-07-24 17:24:59 +0200204 struct lyd_node_term *leaf;
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200205
Radek Krejci710226d2019-07-24 17:24:59 +0200206 /* check hashes */
Michal Vasko9f96a052020-03-10 09:41:45 +0100207 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200208 assert_non_null(tree);
209 assert_int_equal(LYS_LIST, tree->schema->nodetype);
210 assert_string_equal("l1", tree->schema->name);
211 list = (struct lyd_node_inner*)tree;
212 LY_LIST_FOR(list->child, iter) {
213 assert_int_not_equal(0, iter->hash);
214 }
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200215 lyd_free_all(tree);
Radek Krejci710226d2019-07-24 17:24:59 +0200216
Michal Vasko9f96a052020-03-10 09:41:45 +0100217 /* missing keys */
218 data = "<l1 xmlns=\"urn:tests:a\"><c>c</c><b>b</b></l1>";
219 assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
220 logbuf_assert("List instance is missing its key \"a\". /a:l1[b='b'][c='c']");
221
222 data = "<l1 xmlns=\"urn:tests:a\"><a>a</a></l1>";
223 assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
224 logbuf_assert("List instance is missing its key \"b\". /a:l1[a='a']");
225
226 data = "<l1 xmlns=\"urn:tests:a\"><b>b</b><a>a</a></l1>";
227 assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
228 logbuf_assert("List instance is missing its key \"c\". /a:l1[a='a'][b='b']");
229
230 /* key duplicate */
231 data = "<l1 xmlns=\"urn:tests:a\"><c>c</c><b>b</b><a>a</a><c>d</c></l1>";
232 assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
233 logbuf_assert("Duplicate instance of \"c\". /a:l1[a='a'][b='b'][c='d'][c='c']/c");
234
Radek Krejci710226d2019-07-24 17:24:59 +0200235 /* keys order */
236 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 +0100237 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejci710226d2019-07-24 17:24:59 +0200238 assert_non_null(tree);
239 assert_int_equal(LYS_LIST, tree->schema->nodetype);
240 assert_string_equal("l1", tree->schema->name);
241 list = (struct lyd_node_inner*)tree;
242 assert_non_null(leaf = (struct lyd_node_term*)list->child);
243 assert_string_equal("a", leaf->schema->name);
244 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
245 assert_string_equal("b", leaf->schema->name);
246 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
247 assert_string_equal("c", leaf->schema->name);
248 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
249 assert_string_equal("d", leaf->schema->name);
250 logbuf_assert("Invalid position of the key \"b\" in a list.");
251 lyd_free_all(tree);
252
253 data = "<l1 xmlns=\"urn:tests:a\"><c>c</c><b>b</b><a>a</a></l1>";
Michal Vasko9f96a052020-03-10 09:41:45 +0100254 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejci710226d2019-07-24 17:24:59 +0200255 assert_non_null(tree);
256 assert_int_equal(LYS_LIST, tree->schema->nodetype);
257 assert_string_equal("l1", tree->schema->name);
258 list = (struct lyd_node_inner*)tree;
259 assert_non_null(leaf = (struct lyd_node_term*)list->child);
260 assert_string_equal("a", leaf->schema->name);
261 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
262 assert_string_equal("b", leaf->schema->name);
263 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
264 assert_string_equal("c", leaf->schema->name);
265 logbuf_assert("Invalid position of the key \"a\" in a list.");
266 logbuf_clean();
267 lyd_free_all(tree);
268
Michal Vasko9f96a052020-03-10 09:41:45 +0100269 assert_int_equal(LY_EVALID, lyd_parse_xml_data(ctx, data, LYD_OPT_STRICT, &tree));
Radek Krejci710226d2019-07-24 17:24:59 +0200270 logbuf_assert("Invalid position of the key \"b\" in a list. Line number 1.");
271
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200272 *state = NULL;
273}
274
Radek Krejcib6f7ae52019-07-19 10:31:42 +0200275static void
276test_container(void **state)
277{
278 *state = test_container;
279
280 const char *data = "<c xmlns=\"urn:tests:a\"/>";
281 struct lyd_node *tree;
282 struct lyd_node_inner *cont;
283
Michal Vasko9f96a052020-03-10 09:41:45 +0100284 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejcib6f7ae52019-07-19 10:31:42 +0200285 assert_non_null(tree);
286 assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
287 assert_string_equal("c", tree->schema->name);
288 cont = (struct lyd_node_inner*)tree;
289 assert_true(cont->flags & LYD_DEFAULT);
290 lyd_free_all(tree);
291
292 data = "<cp xmlns=\"urn:tests:a\"/>";
Michal Vasko9f96a052020-03-10 09:41:45 +0100293 assert_int_equal(LY_SUCCESS, lyd_parse_xml_data(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejcib6f7ae52019-07-19 10:31:42 +0200294 assert_non_null(tree);
295 assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
296 assert_string_equal("cp", tree->schema->name);
297 cont = (struct lyd_node_inner*)tree;
298 assert_false(cont->flags & LYD_DEFAULT);
299 lyd_free_all(tree);
300
301 *state = NULL;
302}
303
Radek Krejci509e2592019-05-15 16:30:48 +0200304int main(void)
305{
306 const struct CMUnitTest tests[] = {
307 cmocka_unit_test_setup_teardown(test_leaf, setup, teardown),
Radek Krejciee4cab22019-07-17 17:07:47 +0200308 cmocka_unit_test_setup_teardown(test_anydata, setup, teardown),
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200309 cmocka_unit_test_setup_teardown(test_list, setup, teardown),
Radek Krejcib6f7ae52019-07-19 10:31:42 +0200310 cmocka_unit_test_setup_teardown(test_container, setup, teardown),
Radek Krejci509e2592019-05-15 16:30:48 +0200311 };
312
313 return cmocka_run_group_tests(tests, NULL, NULL);
314}