blob: ee42a0b49ff52c8dabd1c70dfe294bc548354bd9 [file] [log] [blame]
Michal Vasko004d3152020-06-11 19:59:22 +02001/**
2 * @file test_new.c
3 * @author: Michal Vasko <mvasko@cesnet.cz>
4 * @brief unit tests for functions for creating data
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 */
14
15#include <stdarg.h>
16#include <stddef.h>
17#include <stdio.h>
18#include <setjmp.h>
19#include <cmocka.h>
20
Radek Krejci70593c12020-06-13 20:48:09 +020021#include "libyang.h"
Michal Vasko004d3152020-06-11 19:59:22 +020022
23#define BUFSIZE 1024
24char logbuf[BUFSIZE] = {0};
25int store = -1; /* negative for infinite logging, positive for limited logging */
26
27struct ly_ctx *ctx; /* context for tests */
28
29/* set to 0 to printing error messages to stderr instead of checking them in code */
30#define ENABLE_LOGGER_CHECKING 1
31
32#if ENABLE_LOGGER_CHECKING
33static void
34logger(LY_LOG_LEVEL level, const char *msg, const char *path)
35{
36 (void) level; /* unused */
37 if (store) {
38 if (path && path[0]) {
39 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
40 } else {
41 strncpy(logbuf, msg, BUFSIZE - 1);
42 }
43 if (store > 0) {
44 --store;
45 }
46 }
47}
48#endif
49
50static int
51setup(void **state)
52{
53 (void) state; /* unused */
54
55 const char *schema_a = "module a {namespace urn:tests:a;prefix a;yang-version 1.1;"
56 "list l1 { key \"a b\"; leaf a {type string;} leaf b {type string;} leaf c {type string;}}"
57 "leaf foo { type uint16;}"
58 "leaf-list ll { type string;}"
59 "container c {leaf-list x {type string;}}"
60 "anydata any {config false;}"
61 "list l2 {config false; container c{leaf x {type string;}}}}";
62
63#if ENABLE_LOGGER_CHECKING
64 ly_set_log_clb(logger, 1);
65#endif
66
67 assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &ctx));
68 assert_non_null(lys_parse_mem(ctx, schema_a, LYS_IN_YANG));
69
70 return 0;
71}
72
73static int
74teardown(void **state)
75{
76#if ENABLE_LOGGER_CHECKING
77 if (*state) {
78 fprintf(stderr, "%s\n", logbuf);
79 }
80#else
81 (void) state; /* unused */
82#endif
83
84 ly_ctx_destroy(ctx, NULL);
85 ctx = NULL;
86
87 return 0;
88}
89
90void
91logbuf_clean(void)
92{
93 logbuf[0] = '\0';
94}
95
96#if ENABLE_LOGGER_CHECKING
97# define logbuf_assert(str) assert_string_equal(logbuf, str)
98#else
99# define logbuf_assert(str)
100#endif
101
102static void
103test_top_level(void **state)
104{
105 *state = test_top_level;
106
107 const struct lys_module *mod;
108 struct lyd_node *node;
109
110 /* we need the module first */
111 mod = ly_ctx_get_module_implemented(ctx, "a");
112 assert_non_null(mod);
113
114 /* list */
115 node = lyd_new_list(NULL, mod, "l1", "val_a", "val_b");
116 assert_non_null(node);
117 lyd_free_tree(node);
118
119 node = lyd_new_list2(NULL, mod, "l1", "[]");
120 assert_null(node);
121 logbuf_assert("Unexpected XPath token ] (]).");
122
123 node = lyd_new_list2(NULL, mod, "l1", "[key1='a'][key2='b']");
124 assert_null(node);
125 logbuf_assert("Not found node \"key1\" in path.");
126
127 node = lyd_new_list2(NULL, mod, "l1", "[a='a'][b='b'][c='c']");
128 assert_null(node);
129 logbuf_assert("Key expected instead of leaf \"c\" in path. /a:l1/c");
130
131 node = lyd_new_list2(NULL, mod, "c", "[a='a'][b='b']");
132 assert_null(node);
133 logbuf_assert("List node \"c\" not found.");
134
135 node = lyd_new_list2(NULL, mod, "l1", "[a='a'][b='b']");
136 assert_non_null(node);
137 lyd_free_tree(node);
138
139 node = lyd_new_list2(NULL, mod, "l1", "[a=''][b='']");
140 assert_non_null(node);
141 lyd_free_tree(node);
142
143 node = lyd_new_list2(NULL, mod, "l1", "[a:a='a'][a:b='b']");
144 assert_non_null(node);
145 lyd_free_tree(node);
146
147 node = lyd_new_list2(NULL, mod, "l1", "[a= 'a']\n[b =\t'b']");
148 assert_non_null(node);
149 lyd_free_tree(node);
150
151 /* leaf */
152 node = lyd_new_term(NULL, mod, "foo", "[a='a'][b='b'][c='c']");
153 assert_null(node);
154 logbuf_assert("Invalid uint16 value \"[a='a'][b='b'][c='c']\". /a:foo");
155
156 node = lyd_new_term(NULL, mod, "c", "value");
157 assert_null(node);
158 logbuf_assert("Term node \"c\" not found.");
159
160 node = lyd_new_term(NULL, mod, "foo", "256");
161 assert_non_null(node);
162 lyd_free_tree(node);
163
164 /* leaf-list */
165 node = lyd_new_term(NULL, mod, "ll", "ahoy");
166 assert_non_null(node);
167 lyd_free_tree(node);
168
169 /* container */
170 node = lyd_new_inner(NULL, mod, "c");
171 assert_non_null(node);
172 lyd_free_tree(node);
173
174 node = lyd_new_inner(NULL, mod, "l1");
175 assert_null(node);
176 logbuf_assert("Inner node (and not a list) \"l1\" not found.");
177
178 node = lyd_new_inner(NULL, mod, "l2");
179 assert_null(node);
180 logbuf_assert("Inner node (and not a list) \"l2\" not found.");
181
182 /* anydata */
183 node = lyd_new_any(NULL, mod, "any", "some-value", LYD_ANYDATA_STRING);
184 assert_non_null(node);
185 lyd_free_tree(node);
186
187 /* key-less list */
188 node = lyd_new_list2(NULL, mod, "l2", "[a='a'][b='b']");
189 assert_null(node);
190 logbuf_assert("List predicate defined for keyless list \"l2\" in path.");
191
192 node = lyd_new_list2(NULL, mod, "l2", "");
193 assert_non_null(node);
194 lyd_free_tree(node);
195
196 node = lyd_new_list2(NULL, mod, "l2", NULL);
197 assert_non_null(node);
198 lyd_free_tree(node);
199
200 node = lyd_new_list(NULL, mod, "l2");
201 assert_non_null(node);
202 lyd_free_tree(node);
203
204 *state = NULL;
205}
206
Michal Vasko00cbf532020-06-15 13:58:47 +0200207static void
208test_opaq(void **state)
209{
210 *state = test_opaq;
211
212 struct lyd_node *root, *node;
213 struct lyd_node_opaq *opq;
214
215 root = lyd_new_opaq(NULL, ctx, "node1", NULL, "my-module");
216 assert_non_null(root);
217 assert_null(root->schema);
218 opq = (struct lyd_node_opaq *)root;
219 assert_string_equal(opq->name, "node1");
220 assert_string_equal(opq->value, "");
221 assert_string_equal(opq->prefix.ns, "my-module");
222
223 node = lyd_new_opaq(root, NULL, "node2", "value", "my-module2");
224 assert_non_null(node);
225 assert_null(node->schema);
226 opq = (struct lyd_node_opaq *)node;
227 assert_string_equal(opq->name, "node2");
228 assert_string_equal(opq->value, "value");
229 assert_string_equal(opq->prefix.ns, "my-module2");
230 assert_ptr_equal(opq->parent, root);
231
232 lyd_free_tree(root);
233
234 *state = NULL;
235}
236
237static void
238test_path(void **state)
239{
240 *state = test_path;
241
242 LY_ERR ret;
243 struct lyd_node *root, *node, *parent;
244 int dynamic;
245
246 /* create 2 nodes */
247 ret = lyd_new_path2(NULL, ctx, "/a:c/x[.='val']", "vvv", 0, 0, &root, &node);
248 assert_int_equal(ret, LY_SUCCESS);
249 assert_non_null(root);
250 assert_string_equal(root->schema->name, "c");
251 assert_non_null(node);
252 assert_string_equal(node->schema->name, "x");
253 assert_string_equal("val", lyd_value2str((struct lyd_node_term *)node, &dynamic));
254 assert_int_equal(dynamic, 0);
255
256 /* append another */
257 ret = lyd_new_path2(root, NULL, "/a:c/x", "val2", 0, 0, &parent, &node);
258 assert_int_equal(ret, LY_SUCCESS);
259 assert_ptr_equal(parent, node);
260 assert_string_equal(node->schema->name, "x");
261 assert_string_equal("val2", lyd_value2str((struct lyd_node_term *)node, &dynamic));
262 assert_int_equal(dynamic, 0);
263
264 /* and a last one */
265 ret = lyd_new_path2(root, NULL, "x", "val3", 0, 0, &parent, &node);
266 assert_int_equal(ret, LY_SUCCESS);
267 assert_ptr_equal(parent, node);
268 assert_string_equal(node->schema->name, "x");
269 assert_string_equal("val3", lyd_value2str((struct lyd_node_term *)node, &dynamic));
270 assert_int_equal(dynamic, 0);
271
272 lyd_free_tree(root);
273
274 /* try LYD_NEWOPT_OPAQ */
275 ret = lyd_new_path2(NULL, ctx, "/a:l1", NULL, 0, 0, NULL, NULL);
276 assert_int_equal(ret, LY_EINVAL);
277 logbuf_assert("Predicate missing for list \"l1\" in path.");
278
279 ret = lyd_new_path2(NULL, ctx, "/a:l1", NULL, 0, LYD_NEWOPT_OPAQ, NULL, &root);
280 assert_int_equal(ret, LY_SUCCESS);
281 assert_non_null(root);
282 assert_null(root->schema);
283
284 lyd_free_tree(root);
285
286 ret = lyd_new_path2(NULL, ctx, "/a:foo", NULL, 0, 0, NULL, NULL);
287 assert_int_equal(ret, LY_EVALID);
288 logbuf_assert("Invalid empty uint16 value. /a:foo");
289
290 ret = lyd_new_path2(NULL, ctx, "/a:foo", NULL, 0, LYD_NEWOPT_OPAQ, NULL, &root);
291 assert_int_equal(ret, LY_SUCCESS);
292 assert_non_null(root);
293 assert_null(root->schema);
294
295 lyd_free_tree(root);
296
297 /* try LYD_NEWOPT_UPDATE */
298 ret = lyd_new_path2(NULL, ctx, "/a:l2[1]/c/x", "val", 0, 0, &root, &node);
299 assert_int_equal(ret, LY_SUCCESS);
300 assert_non_null(root);
301 assert_string_equal(node->schema->name, "x");
302 assert_string_equal("val", lyd_value2str((struct lyd_node_term *)node, &dynamic));
303 assert_int_equal(dynamic, 0);
304
305 ret = lyd_new_path2(root, NULL, "/a:l2[1]/c/x", "val", 0, 0, NULL, &node);
306 assert_int_equal(ret, LY_EEXIST);
307
308 ret = lyd_new_path2(root, NULL, "/a:l2[1]/c/x", "val", 0, LYD_NEWOPT_UPDATE, NULL, &node);
309 assert_int_equal(ret, LY_SUCCESS);
310 assert_null(node);
311
312 ret = lyd_new_path2(root, NULL, "/a:l2[1]/c/x", "val2", 0, LYD_NEWOPT_UPDATE, NULL, &node);
313 assert_int_equal(ret, LY_SUCCESS);
314 assert_non_null(node);
315 assert_string_equal(node->schema->name, "x");
316 assert_string_equal("val2", lyd_value2str((struct lyd_node_term *)node, &dynamic));
317 assert_int_equal(dynamic, 0);
318
319 lyd_free_tree(root);
320
321 *state = NULL;
322}
323
Michal Vasko004d3152020-06-11 19:59:22 +0200324int main(void)
325{
326 const struct CMUnitTest tests[] = {
327 cmocka_unit_test_setup_teardown(test_top_level, setup, teardown),
Michal Vasko00cbf532020-06-15 13:58:47 +0200328 cmocka_unit_test_setup_teardown(test_opaq, setup, teardown),
329 cmocka_unit_test_setup_teardown(test_path, setup, teardown),
Michal Vasko004d3152020-06-11 19:59:22 +0200330 };
331
332 return cmocka_run_group_tests(tests, NULL, NULL);
333}