blob: dcf6970521e8a47f2c0ecf2bc1fbb7a783669522 [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 Vasko9b368d32020-02-14 13:53:31 +0100117 assert_int_equal(LY_SUCCESS, lyd_parse_xml(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>";
134 assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
135 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>";
146 assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
147 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 Vasko9b368d32020-02-14 13:53:31 +0100170 assert_int_equal(LY_SUCCESS, lyd_parse_xml(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 Vasko9b368d32020-02-14 13:53:31 +0100193 assert_int_equal(LY_SUCCESS, lyd_parse_xml(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
203 /* keys order */
204 data = "<l1 xmlns=\"urn:tests:a\"><d>d</d><a>a</a><c>c</c><b>b</b></l1>";
Michal Vasko9b368d32020-02-14 13:53:31 +0100205 assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejci710226d2019-07-24 17:24:59 +0200206 assert_non_null(tree);
207 assert_int_equal(LYS_LIST, tree->schema->nodetype);
208 assert_string_equal("l1", tree->schema->name);
209 list = (struct lyd_node_inner*)tree;
210 assert_non_null(leaf = (struct lyd_node_term*)list->child);
211 assert_string_equal("a", leaf->schema->name);
212 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
213 assert_string_equal("b", leaf->schema->name);
214 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
215 assert_string_equal("c", leaf->schema->name);
216 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
217 assert_string_equal("d", leaf->schema->name);
218 logbuf_assert("Invalid position of the key \"b\" in a list.");
219 lyd_free_all(tree);
220
221 data = "<l1 xmlns=\"urn:tests:a\"><c>c</c><b>b</b><a>a</a></l1>";
Michal Vasko9b368d32020-02-14 13:53:31 +0100222 assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejci710226d2019-07-24 17:24:59 +0200223 assert_non_null(tree);
224 assert_int_equal(LYS_LIST, tree->schema->nodetype);
225 assert_string_equal("l1", tree->schema->name);
226 list = (struct lyd_node_inner*)tree;
227 assert_non_null(leaf = (struct lyd_node_term*)list->child);
228 assert_string_equal("a", leaf->schema->name);
229 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
230 assert_string_equal("b", leaf->schema->name);
231 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
232 assert_string_equal("c", leaf->schema->name);
233 logbuf_assert("Invalid position of the key \"a\" in a list.");
234 logbuf_clean();
235 lyd_free_all(tree);
236
Michal Vaskoa3881362020-01-21 15:57:35 +0100237 assert_int_equal(LY_EVALID, lyd_parse_xml(ctx, data, LYD_OPT_STRICT, &tree));
Radek Krejci710226d2019-07-24 17:24:59 +0200238 logbuf_assert("Invalid position of the key \"b\" in a list. Line number 1.");
239
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200240 *state = NULL;
241}
242
Radek Krejcib6f7ae52019-07-19 10:31:42 +0200243static void
244test_container(void **state)
245{
246 *state = test_container;
247
248 const char *data = "<c xmlns=\"urn:tests:a\"/>";
249 struct lyd_node *tree;
250 struct lyd_node_inner *cont;
251
Michal Vasko9b368d32020-02-14 13:53:31 +0100252 assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejcib6f7ae52019-07-19 10:31:42 +0200253 assert_non_null(tree);
254 assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
255 assert_string_equal("c", tree->schema->name);
256 cont = (struct lyd_node_inner*)tree;
257 assert_true(cont->flags & LYD_DEFAULT);
258 lyd_free_all(tree);
259
260 data = "<cp xmlns=\"urn:tests:a\"/>";
Michal Vasko9b368d32020-02-14 13:53:31 +0100261 assert_int_equal(LY_SUCCESS, lyd_parse_xml(ctx, data, LYD_VALOPT_DATA_ONLY, &tree));
Radek Krejcib6f7ae52019-07-19 10:31:42 +0200262 assert_non_null(tree);
263 assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
264 assert_string_equal("cp", tree->schema->name);
265 cont = (struct lyd_node_inner*)tree;
266 assert_false(cont->flags & LYD_DEFAULT);
267 lyd_free_all(tree);
268
269 *state = NULL;
270}
271
Radek Krejci509e2592019-05-15 16:30:48 +0200272int main(void)
273{
274 const struct CMUnitTest tests[] = {
275 cmocka_unit_test_setup_teardown(test_leaf, setup, teardown),
Radek Krejciee4cab22019-07-17 17:07:47 +0200276 cmocka_unit_test_setup_teardown(test_anydata, setup, teardown),
Radek Krejci1f05b6a2019-07-18 16:15:06 +0200277 cmocka_unit_test_setup_teardown(test_list, setup, teardown),
Radek Krejcib6f7ae52019-07-19 10:31:42 +0200278 cmocka_unit_test_setup_teardown(test_container, setup, teardown),
Radek Krejci509e2592019-05-15 16:30:48 +0200279 };
280
281 return cmocka_run_group_tests(tests, NULL, NULL);
282}