blob: 7539dc7439914367726095bc1c04c4c64c43e2fe [file] [log] [blame]
Radek Krejci1798aae2020-07-14 13:26:06 +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
15#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
23#include "context.h"
24#include "parser.h"
25#include "parser_data.h"
26#include "printer.h"
27#include "printer_data.h"
28#include "tests/config.h"
29#include "tree_data_internal.h"
30#include "tree_schema.h"
31
32#define BUFSIZE 1024
33char logbuf[BUFSIZE] = {0};
34int store = -1; /* negative for infinite logging, positive for limited logging */
35
36struct ly_ctx *ctx; /* context for tests */
37
38/* set to 0 to printing error messages to stderr instead of checking them in code */
39#define ENABLE_LOGGER_CHECKING 1
40
41#if ENABLE_LOGGER_CHECKING
42static void
43logger(LY_LOG_LEVEL level, const char *msg, const char *path)
44{
45 (void) level; /* unused */
46 if (store) {
47 if (path && path[0]) {
48 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
49 } else {
50 strncpy(logbuf, msg, BUFSIZE - 1);
51 }
52 if (store > 0) {
53 --store;
54 }
55 }
56}
57#endif
58
59static int
60setup(void **state)
61{
62 (void) state; /* unused */
63
64 const char *schema_a = "module a {namespace urn:tests:a;prefix a;yang-version 1.1; import ietf-yang-metadata {prefix md;}"
65 "md:annotation hint { type int8;}"
66 "list l1 { key \"a b c\"; leaf a {type string;} leaf b {type string;} leaf c {type int16;} leaf d {type string;}}"
67 "leaf foo { type string;}"
68 "container c {"
69 "leaf x {type string;}"
70 "action act { input { leaf al {type string;} } output { leaf al {type uint8;} } }"
71 "notification n1 { leaf nl {type string;} }"
72 "}"
73 "container cp {presence \"container switch\"; leaf y {type string;} leaf z {type int8;}}"
74 "anydata any {config false;}"
75 "leaf-list ll1 { type uint8; }"
76 "leaf foo2 { type string; default \"default-val\"; }"
77 "leaf foo3 { type uint32; }"
78 "notification n2;}";
79 const struct lys_module *mod;
80
81#if ENABLE_LOGGER_CHECKING
82 ly_set_log_clb(logger, 1);
83#endif
84
85 assert_int_equal(LY_SUCCESS, ly_ctx_new(TESTS_DIR_MODULES_YANG, 0, &ctx));
86 assert_non_null(ly_ctx_load_module(ctx, "ietf-netconf-with-defaults", "2011-06-01"));
87 assert_non_null((mod = ly_ctx_load_module(ctx, "ietf-netconf", "2011-06-01")));
88 assert_int_equal(LY_SUCCESS, lys_feature_enable(mod, "writable-running"));
89 assert_int_equal(LY_SUCCESS, lys_parse_mem(ctx, schema_a, LYS_IN_YANG, NULL));
90
91 return 0;
92}
93
94static int
95teardown(void **state)
96{
97#if ENABLE_LOGGER_CHECKING
98 if (*state) {
99 fprintf(stderr, "%s\n", logbuf);
100 }
101#else
102 (void) state; /* unused */
103#endif
104
105 ly_ctx_destroy(ctx, NULL);
106 ctx = NULL;
107
108 return 0;
109}
110
111void
112logbuf_clean(void)
113{
114 logbuf[0] = '\0';
115}
116
117#if ENABLE_LOGGER_CHECKING
118# define logbuf_assert(str) assert_string_equal(logbuf, str)
119#else
120# define logbuf_assert(str)
121#endif
122
123static void
124test_leaf(void **state)
125{
126 *state = test_leaf;
127
128 const char *data = "{\"a:foo\":\"foo value\"}";
129 struct lyd_node *tree;
130 struct lyd_node_term *leaf;
131
132 char *printed;
133 struct ly_out *out;
134 assert_int_equal(LY_SUCCESS, ly_out_new_memory(&printed, 0, &out));
135
136 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
137 assert_non_null(tree);
138 assert_int_equal(LYS_LEAF, tree->schema->nodetype);
139 assert_string_equal("foo", tree->schema->name);
140 leaf = (struct lyd_node_term*)tree;
141 assert_string_equal("foo value", leaf->value.original);
142
143 assert_int_equal(LYS_LEAF, tree->next->next->schema->nodetype);
144 assert_string_equal("foo2", tree->next->next->schema->name);
145 leaf = (struct lyd_node_term*)tree->next->next;
146 assert_string_equal("default-val", leaf->value.original);
147 assert_true(leaf->flags & LYD_DEFAULT);
148
149 lyd_print_tree(out, tree, LYD_JSON, 0);
150 assert_string_equal(printed, data);
151 ly_out_reset(out);
152 lyd_free_all(tree);
153
154 /* make foo2 explicit */
155 data = "{\"a:foo2\":\"default-val\"}";
156 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
157 assert_non_null(tree);
158 assert_int_equal(LYS_LEAF, tree->schema->nodetype);
159 assert_string_equal("foo2", tree->schema->name);
160 leaf = (struct lyd_node_term*)tree;
161 assert_string_equal("default-val", leaf->value.original);
162 assert_false(leaf->flags & LYD_DEFAULT);
163
164 lyd_print_tree(out, tree, LYD_JSON, 0);
165 assert_string_equal(printed, data);
166 ly_out_reset(out);
167 lyd_free_all(tree);
168
169 /* parse foo2 but make it implicit */
170 data = "{\"a:foo2\" : \"default-val\", \"@a:foo2\" : { \"ietf-netconf-with-defaults:default\" : true }}";
171 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
172 assert_non_null(tree);
173 assert_int_equal(LYS_LEAF, tree->schema->nodetype);
174 assert_string_equal("foo2", tree->schema->name);
175 leaf = (struct lyd_node_term*)tree;
176 assert_string_equal("default-val", leaf->value.original);
177 assert_true(leaf->flags & LYD_DEFAULT);
178
179 lyd_free_all(tree);
180
181 /* multiple meatadata hint and unknown metadata xxx supposed to be skipped since it is from missing schema */
182 data = "{\"@a:foo\" : { \"a:hint\" : 1, \"a:hint\" : 2, \"x:xxx\" : { \"value\" : \"/x:no/x:yes\" }}, \"a:foo\" : \"xxx\"}";
183 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
184 assert_non_null(tree);
185 assert_int_equal(LYS_LEAF, tree->schema->nodetype);
186 assert_string_equal("foo", tree->schema->name);
187 assert_non_null(tree->meta);
188 assert_string_equal("hint", tree->meta->name);
189 assert_int_equal(LY_TYPE_INT8, tree->meta->value.realtype->basetype);
190 assert_string_equal("1", tree->meta->value.original);
191 assert_int_equal(1, tree->meta->value.int8);
192 assert_ptr_equal(tree, tree->meta->parent);
193 assert_non_null(tree->meta->next);
194 assert_string_equal("hint", tree->meta->next->name);
195 assert_int_equal(LY_TYPE_INT8, tree->meta->next->value.realtype->basetype);
196 assert_string_equal("2", tree->meta->next->value.original);
197 assert_int_equal(2, tree->meta->next->value.int8);
198 assert_ptr_equal(tree, tree->meta->next->parent);
199 assert_null(tree->meta->next->next);
200
201 ly_out_free(out, NULL, 1);
202 lyd_free_all(tree);
203
204 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
205 logbuf_assert("Unknown (or not implemented) YANG module \"x\" for metadata \"x:xxx\". /a:foo");
206
207 /* missing referenced metadata node */
208 data = "{\"@a:foo\" : { \"a:hint\" : 1 }}";
209 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
210 logbuf_assert("Missing JSON data instance to be coupled with @a:foo metadata. /");
211
212 /* missing namespace for meatadata*/
213 data = "{\"a:foo\" : \"value\", \"@a:foo\" : { \"hint\" : 1 }}";
214 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
215 logbuf_assert("Metadata in JSON must be namespace-qualified, missing prefix for \"hint\". /a:foo");
216
217 *state = NULL;
218}
219
220static void
221test_leaflist(void **state)
222{
223 *state = test_leaflist;
224
225 const char *data = "{ \"a:ll1\" : [10,11] }";
226 struct lyd_node *tree;
227 struct lyd_node_term *ll;
228
229 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
230 assert_non_null(tree);
231 assert_int_equal(LYS_LEAFLIST, tree->schema->nodetype);
232 assert_string_equal("ll1", tree->schema->name);
233 ll = (struct lyd_node_term*)tree;
234 assert_string_equal("10", ll->value.original);
235
236 assert_non_null(tree->next);
237 assert_int_equal(LYS_LEAFLIST, tree->next->schema->nodetype);
238 assert_string_equal("ll1", tree->next->schema->name);
239 ll = (struct lyd_node_term*)tree->next;
240 assert_string_equal("11", ll->value.original);
241
242 lyd_free_all(tree);
243
244 /* simple metadata */
245 data = "{ \"a:ll1\" : [10,11], \"@a:ll1\" : [null, {\"a:hint\" : 2}] }";
246 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
247 assert_non_null(tree);
248 assert_int_equal(LYS_LEAFLIST, tree->schema->nodetype);
249 assert_string_equal("ll1", tree->schema->name);
250 ll = (struct lyd_node_term*)tree;
251 assert_string_equal("10", ll->value.original);
252 assert_null(ll->meta);
253
254 assert_non_null(tree->next);
255 assert_int_equal(LYS_LEAFLIST, tree->next->schema->nodetype);
256 assert_string_equal("ll1", tree->next->schema->name);
257 ll = (struct lyd_node_term*)tree->next;
258 assert_string_equal("11", ll->value.original);
259 assert_non_null(ll->meta);
260 assert_string_equal("2", ll->meta->value.original);
261 assert_null(ll->meta->next);
262
263 lyd_free_all(tree);
264
265 /* multiple meatadata hint and unknown metadata xxx supposed to be skipped since it is from missing schema */
266 data = "{\"@a:ll1\" : [{\"a:hint\" : 1, \"x:xxx\" : { \"value\" : \"/x:no/x:yes\" }, \"a:hint\" : 10},null,{\"a:hint\" : 3}], \"a:ll1\" : [1,2,3]}";
267 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
268 assert_non_null(tree);
269 assert_int_equal(LYS_LEAFLIST, tree->schema->nodetype);
270 assert_string_equal("ll1", tree->schema->name);
271 ll = (struct lyd_node_term*)tree;
272 assert_string_equal("1", ll->value.original);
273 assert_non_null(ll->meta);
274 assert_string_equal("hint", ll->meta->name);
275 assert_int_equal(LY_TYPE_INT8, ll->meta->value.realtype->basetype);
276 assert_string_equal("1", ll->meta->value.original);
277 assert_int_equal(1, ll->meta->value.int8);
278 assert_ptr_equal(ll, ll->meta->parent);
279 assert_non_null(ll->meta->next);
280 assert_string_equal("hint", ll->meta->next->name);
281 assert_int_equal(LY_TYPE_INT8, ll->meta->next->value.realtype->basetype);
282 assert_string_equal("10", ll->meta->next->value.original);
283 assert_int_equal(10, ll->meta->next->value.int8);
284 assert_ptr_equal(ll, ll->meta->next->parent);
285 assert_null(ll->meta->next->next);
286
287 assert_non_null(tree->next);
288 assert_int_equal(LYS_LEAFLIST, tree->next->schema->nodetype);
289 assert_string_equal("ll1", tree->next->schema->name);
290 ll = (struct lyd_node_term*)tree->next;
291 assert_string_equal("2", ll->value.original);
292 assert_null(ll->meta);
293
294 assert_non_null(tree->next->next);
295 assert_int_equal(LYS_LEAFLIST, tree->next->next->schema->nodetype);
296 assert_string_equal("ll1", tree->next->next->schema->name);
297 ll = (struct lyd_node_term*)tree->next->next;
298 assert_string_equal("3", ll->value.original);
299 assert_non_null(ll->meta);
300 assert_string_equal("hint", ll->meta->name);
301 assert_int_equal(LY_TYPE_INT8, ll->meta->value.realtype->basetype);
302 assert_string_equal("3", ll->meta->value.original);
303 assert_int_equal(3, ll->meta->value.int8);
304 assert_ptr_equal(ll, ll->meta->parent);
305 assert_null(ll->meta->next);
306
307 lyd_free_all(tree);
308
309 /* missing referenced metadata node */
310 data = "{\"@a:ll1\":[{\"a:hint\":1}]}";
311 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
312 logbuf_assert("Missing JSON data instance to be coupled with @a:ll1 metadata. /");
313
314 data = "{\"a:ll1\":[1],\"@a:ll1\":[{\"a:hint\":1},{\"a:hint\":2}]}";
315 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
316 logbuf_assert("Missing JSON data instance no. 2 of a:ll1 to be coupled with metadata. /");
317
318 data = "{\"@a:ll1\":[{\"a:hint\":1},{\"a:hint\":2},{\"a:hint\":3}],\"a:ll1\" : [1, 2]}";
319 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
320 logbuf_assert("Missing 3rd JSON data instance to be coupled with @a:ll1 metadata. /");
321
322 *state = NULL;
323}
324
325static void
326test_anydata(void **state)
327{
328 *state = test_anydata;
329
330 const char *data;
331 char *str;
332 struct lyd_node *tree;
333
334 struct ly_out *out;
335 assert_int_equal(LY_SUCCESS, ly_out_new_memory(&str, 0, &out));
336
337 data = "{\"a:any\":{\"x:element1\":{\"element2\":\"/a:some/a:path\",\"list\":[{},{\"key\":\"a\"}]}}}";
338 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
339 assert_non_null(tree);
340 assert_int_equal(LYS_ANYDATA, tree->schema->nodetype);
341 assert_string_equal("any", tree->schema->name);
342
343 lyd_print_tree(out, tree, LYD_JSON, 0);
344 assert_string_equal(str, data);
345 ly_out_reset(out);
346
347 lyd_free_all(tree);
348 ly_out_free(out, NULL, 1);
349
350 *state = NULL;
351}
352
353static void
354test_list(void **state)
355{
356 *state = test_list;
357
358 const char *data = "{ \"a:l1\" : [{ \"a\":\"one\",\"b\":\"one\",\"c\":1 }]} ";
359 struct lyd_node *tree, *iter;
360 struct lyd_node_inner *list;
361 struct lyd_node_term *leaf;
362
363 /* check hashes */
364 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
365 assert_non_null(tree);
366 assert_int_equal(LYS_LIST, tree->schema->nodetype);
367 assert_string_equal("l1", tree->schema->name);
368 list = (struct lyd_node_inner*)tree;
369 LY_LIST_FOR(list->child, iter) {
370 assert_int_not_equal(0, iter->hash);
371 }
372 lyd_free_all(tree);
373
374 /* missing keys */
375 data = "{ \"a:l1\": [ {\"c\" : 1, \"b\" : \"b\"}]}";
376 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
377 logbuf_assert("List instance is missing its key \"a\". /a:l1[b='b'][c='1']");
378
379 data = "{ \"a:l1\": [ {\"a\" : \"a\"}]}";
380 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
381 logbuf_assert("List instance is missing its key \"b\". /a:l1[a='a']");
382
383 data = "{ \"a:l1\": [ {\"b\" : \"b\", \"a\" : \"a\"}]}";
384 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
385 logbuf_assert("List instance is missing its key \"c\". /a:l1[a='a'][b='b']");
386
387 /* key duplicate */
388 data = "{ \"a:l1\": [ {\"c\" : 1, \"b\" : \"b\", \"a\" : \"a\", \"c\" : 1}]}";
389 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
390 logbuf_assert("Duplicate instance of \"c\". /a:l1[a='a'][b='b'][c='1'][c='1']/c");
391
392 /* keys order, in contrast to XML, JSON accepts keys in any order even in strict mode */
393 logbuf_clean();
394 data = "{ \"a:l1\": [ {\"d\" : \"d\", \"a\" : \"a\", \"c\" : 1, \"b\" : \"b\"}]}";
395 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
396 assert_non_null(tree);
397 assert_int_equal(LYS_LIST, tree->schema->nodetype);
398 assert_string_equal("l1", tree->schema->name);
399 list = (struct lyd_node_inner*)tree;
400 assert_non_null(leaf = (struct lyd_node_term*)list->child);
401 assert_string_equal("a", leaf->schema->name);
402 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
403 assert_string_equal("b", leaf->schema->name);
404 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
405 assert_string_equal("c", leaf->schema->name);
406 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
407 assert_string_equal("d", leaf->schema->name);
408 logbuf_assert("");
409 lyd_free_all(tree);
410
411 /* */
412 data = "{ \"a:l1\": [ {\"c\" : 1, \"b\" : \"b\", \"a\" : \"a\"}]}";
413 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &tree));
414 assert_non_null(tree);
415 assert_int_equal(LYS_LIST, tree->schema->nodetype);
416 assert_string_equal("l1", tree->schema->name);
417 list = (struct lyd_node_inner*)tree;
418 assert_non_null(leaf = (struct lyd_node_term*)list->child);
419 assert_string_equal("a", leaf->schema->name);
420 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
421 assert_string_equal("b", leaf->schema->name);
422 assert_non_null(leaf = (struct lyd_node_term*)leaf->next);
423 assert_string_equal("c", leaf->schema->name);
424 logbuf_assert("");
425 lyd_free_all(tree);
426
427 data = "{\"a:cp\" : { \"@\" : { \"a:hint\" : 1 }}}";
428 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
429 assert_non_null(tree);
430 assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
431 assert_string_equal("cp", tree->schema->name);
432 assert_non_null(tree->meta);
433 assert_string_equal("hint", tree->meta->name);
434 assert_string_equal("1", tree->meta->value.original);
435 assert_ptr_equal(tree, tree->meta->parent);
436 assert_null(tree->meta->next);
437 lyd_free_all(tree);
438
439 *state = NULL;
440}
441
442static void
443test_container(void **state)
444{
445 *state = test_container;
446
447 const char *data = " {\"a:c\" : {}}";
448 struct lyd_node *tree;
449 struct lyd_node_inner *cont;
450
451 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
452 assert_non_null(tree);
453 assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
454 assert_string_equal("c", tree->schema->name);
455 cont = (struct lyd_node_inner*)tree;
456 assert_true(cont->flags & LYD_DEFAULT);
457 lyd_free_all(tree);
458
459 data = "{\"a:cp\" : {}}";
460 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
461 assert_non_null(tree);
462 assert_int_equal(LYS_CONTAINER, tree->schema->nodetype);
463 assert_string_equal("cp", tree->schema->name);
464 cont = (struct lyd_node_inner*)tree;
465 assert_false(cont->flags & LYD_DEFAULT);
466 lyd_free_all(tree);
467
468 *state = NULL;
469}
470
471static void
472test_opaq(void **state)
473{
474 *state = test_opaq;
475
476 const char *data;
477 char *str;
478 struct lyd_node *tree;
479
480 struct ly_out *out;
481 assert_int_equal(LY_SUCCESS, ly_out_new_memory(&str, 0, &out));
482
483 /* invalid value, no flags */
484 data = "{\"a:foo3\":[null]}";
485 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
486 logbuf_assert("Invalid empty uint32 value. /a:foo3");
487 assert_null(tree);
488
489 /* opaq flag */
490 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree));
491 assert_non_null(tree);
492 assert_null(tree->schema);
493 assert_string_equal(((struct lyd_node_opaq *)tree)->name, "foo3");
494 assert_string_equal(((struct lyd_node_opaq *)tree)->value, "");
495
496 lyd_print_tree(out, tree, LYD_JSON, 0);
497 assert_string_equal(str, data);
498 ly_out_reset(out);
499 lyd_free_all(tree);
500
501 /* missing key, no flags */
502 data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"d\":\"val_d\"}]}";
503 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
504 logbuf_assert("List instance is missing its key \"c\". /a:l1[a='val_a'][b='val_b']");
505 assert_null(tree);
506
507 /* opaq flag */
508 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree));
509 assert_non_null(tree);
510 assert_null(tree->schema);
511 assert_string_equal(((struct lyd_node_opaq *)tree)->name, "l1");
512 assert_string_equal(((struct lyd_node_opaq *)tree)->value, "");
513
514 lyd_print_tree(out, tree, LYD_JSON, 0);
515 assert_string_equal(str, data);
516 ly_out_reset(out);
517 lyd_free_all(tree);
518
519 /* invalid key, no flags */
520 data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}";
521 assert_int_equal(LY_EVALID, lyd_parse_data_mem(ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
522 logbuf_assert("Invalid int16 value \"val_c\". /a:l1/c");
523 assert_null(tree);
524
525 /* opaq flag */
526 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree));
527 assert_non_null(tree);
528 assert_null(tree->schema);
529 assert_string_equal(((struct lyd_node_opaq *)tree)->name, "l1");
530 assert_string_equal(((struct lyd_node_opaq *)tree)->value, "");
531
532 lyd_print_tree(out, tree, LYD_JSON, 0);
533 assert_string_equal(str, data);
534 ly_out_reset(out);
535 lyd_free_all(tree);
536
537 data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":{\"val\":\"val_c\"}}]}";
538 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree));
539 assert_non_null(tree);
540 assert_null(tree->schema);
541 assert_string_equal(((struct lyd_node_opaq *)tree)->name, "l1");
542 assert_string_equal(((struct lyd_node_opaq *)tree)->value, "");
543
544 lyd_print_tree(out, tree, LYD_JSON, 0);
545 assert_string_equal(str, data);
546 ly_out_reset(out);
547 lyd_free_all(tree);
548
549 data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\"}]}";
550 assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(ctx, data, LYD_JSON, LYD_PARSE_OPAQ, LYD_VALIDATE_PRESENT, &tree));
551 assert_non_null(tree);
552 assert_null(tree->schema);
553 assert_string_equal(((struct lyd_node_opaq *)tree)->name, "l1");
554 assert_string_equal(((struct lyd_node_opaq *)tree)->value, "");
555
556 lyd_print_tree(out, tree, LYD_JSON, 0);
557 assert_string_equal(str, data);
558 ly_out_reset(out);
559 lyd_free_all(tree);
560
561 ly_out_free(out, NULL, 1);
562
563 *state = NULL;
564}
565
566static void
567test_rpc(void **state)
568{
569 *state = test_rpc;
570
571 const char *data;
572 struct ly_in *in;
573 char *str;
574 struct lyd_node *tree, *op;
575 const struct lyd_node *node;
576
577 struct ly_out *out;
578 assert_int_equal(LY_SUCCESS, ly_out_new_memory(&str, 0, &out));
579
580 data = "{\"ietf-netconf:rpc\":{\"edit-config\":{"
581 "\"target\":{\"running\":[null]},"
582 "\"config\":{\"a:cp\":{\"z\":[null],\"@z\":{\"ietf-netconf:operation\":\"replace\"}},"
583 "\"a:l1\":[{\"@\":{\"ietf-netconf:operation\":\"replace\"},\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}"
584 "}}}";
585 assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
586 assert_int_equal(LY_SUCCESS, lyd_parse_rpc(ctx, in, LYD_JSON, &tree, &op));
587 ly_in_free(in, 0);
588
589 assert_non_null(op);
590 assert_string_equal(op->schema->name, "edit-config");
591
592 assert_non_null(tree);
593 assert_null(tree->schema);
594 assert_string_equal(((struct lyd_node_opaq *)tree)->name, "rpc");
595 /* TODO support generic attributes in JSON ?
596 assert_non_null(((struct lyd_node_opaq *)tree)->attr);
597 */
598 node = lyd_node_children(tree, 0);
599 assert_string_equal(node->schema->name, "edit-config");
600 node = lyd_node_children(node, 0)->next;
601 assert_string_equal(node->schema->name, "config");
602
603 node = ((struct lyd_node_any *)node)->value.tree;
604 assert_non_null(node->schema);
605 assert_string_equal(node->schema->name, "cp");
606 node = lyd_node_children(node, 0);
607 /* z has no value */
608 assert_null(node->schema);
609 assert_string_equal(((struct lyd_node_opaq *)node)->name, "z");
610 node = node->parent->next;
611 /* l1 key c has invalid value so it is at the end */
612 assert_null(node->schema);
613 assert_string_equal(((struct lyd_node_opaq *)node)->name, "l1");
614
615 lyd_print_tree(out, tree, LYD_JSON, 0);
616 assert_string_equal(str, data);
617 ly_out_reset(out);
618 lyd_free_all(tree);
619
620 /* wrong namespace, element name, whatever... */
621 /* TODO */
622
623 ly_out_free(out, NULL, 1);
624
625 *state = NULL;
626}
627
628static void
629test_action(void **state)
630{
631 *state = test_action;
632
633 const char *data;
634 struct ly_in *in;
635 char *str;
636 struct lyd_node *tree, *op;
637 const struct lyd_node *node;
638
639 struct ly_out *out;
640 assert_int_equal(LY_SUCCESS, ly_out_new_memory(&str, 0, &out));
641
642 data = "{\"ietf-netconf:rpc\":{\"yang:action\":{\"a:c\":{\"act\":{\"al\":\"value\"}}}}}";
643 assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
644 assert_int_equal(LY_SUCCESS, lyd_parse_rpc(ctx, in, LYD_JSON, &tree, &op));
645 ly_in_free(in, 0);
646
647 assert_non_null(op);
648 assert_string_equal(op->schema->name, "act");
649
650 assert_non_null(tree);
651 assert_null(tree->schema);
652 assert_string_equal(((struct lyd_node_opaq *)tree)->name, "rpc");
653 assert_null(((struct lyd_node_opaq *)tree)->attr);
654 node = lyd_node_children(tree, 0);
655 assert_null(node->schema);
656 assert_string_equal(((struct lyd_node_opaq *)node)->name, "action");
657 assert_null(((struct lyd_node_opaq *)node)->attr);
658
659 lyd_print_tree(out, tree, LYD_JSON, 0);
660 assert_string_equal(str, data);
661 ly_out_reset(out);
662 lyd_free_all(tree);
663
664 /* wrong namespace, element name, whatever... */
665 /* TODO */
666
667 ly_out_free(out, NULL, 1);
668
669 *state = NULL;
670}
671
672static void
673test_notification(void **state)
674{
675 *state = test_notification;
676
677 const char *data;
678 struct ly_in *in;
679 char *str;
680 struct lyd_node *tree, *ntf;
681 const struct lyd_node *node;
682
683 struct ly_out *out;
684 assert_int_equal(LY_SUCCESS, ly_out_new_memory(&str, 0, &out));
685
686 data = "{\"ietf-restconf:notification\":{\"eventTime\":\"2037-07-08T00:01:00Z\",\"a:c\":{\"n1\":{\"nl\":\"value\"}}}}";
687 assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
688 assert_int_equal(LY_SUCCESS, lyd_parse_notif(ctx, in, LYD_JSON, &tree, &ntf));
689 ly_in_free(in, 0);
690
691 assert_non_null(ntf);
692 assert_string_equal(ntf->schema->name, "n1");
693
694 assert_non_null(tree);
695 assert_null(tree->schema);
696 assert_string_equal(((struct lyd_node_opaq *)tree)->name, "notification");
697 assert_null(((struct lyd_node_opaq *)tree)->attr);
698 node = lyd_node_children(tree, 0);
699 assert_null(node->schema);
700 assert_string_equal(((struct lyd_node_opaq *)node)->name, "eventTime");
701 assert_string_equal(((struct lyd_node_opaq *)node)->value, "2037-07-08T00:01:00Z");
702 assert_null(((struct lyd_node_opaq *)node)->attr);
703 node = node->next;
704 assert_non_null(node->schema);
705 assert_string_equal(node->schema->name, "c");
706
707 lyd_print_tree(out, tree, LYD_JSON, 0);
708 assert_string_equal(str, data);
709 ly_out_reset(out);
710 lyd_free_all(tree);
711
712 /* top-level notif without envelope */
713 data = "{\"a:n2\":{}}";
714 assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
715 assert_int_equal(LY_SUCCESS, lyd_parse_notif(ctx, in, LYD_JSON, &tree, &ntf));
716 ly_in_free(in, 0);
717
718 assert_non_null(ntf);
719 assert_string_equal(ntf->schema->name, "n2");
720
721 assert_non_null(tree);
722 assert_ptr_equal(ntf, tree);
723
724 lyd_print_tree(out, tree, LYD_JSON, 0);
725 assert_string_equal(str, data);
726 ly_out_reset(out);
727 lyd_free_all(tree);
728
729 /* wrong namespace, element name, whatever... */
730 /* TODO */
731
732 ly_out_free(out, NULL, 1);
733
734 *state = NULL;
735}
736
737static void
738test_reply(void **state)
739{
740 *state = test_reply;
741
742 const char *data;
743 struct ly_in *in;
744 char *str;
745 struct lyd_node *request, *tree, *op;
746 const struct lyd_node *node;
747
748 struct ly_out *out;
749 assert_int_equal(LY_SUCCESS, ly_out_new_memory(&str, 0, &out));
750
751 data = "{\"a:c\":{\"act\":{\"al\":\"value\"}}}";
752 assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
753 assert_int_equal(LY_SUCCESS, lyd_parse_rpc(ctx, in, LYD_JSON, &request, NULL));
754 ly_in_free(in, 0);
755
756 data = "{\"ietf-netconf:rpc-reply\":{\"a:al\":25}}";
757 assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
758 assert_int_equal(LY_SUCCESS, lyd_parse_reply(request, in, LYD_JSON, &tree, &op));
759 ly_in_free(in, 0);
760 lyd_free_all(request);
761
762 assert_non_null(op);
763 assert_string_equal(op->schema->name, "act");
764 node = lyd_node_children(op, 0);
765 assert_non_null(node->schema);
766 assert_string_equal(node->schema->name, "al");
767 assert_true(node->schema->flags & LYS_CONFIG_R);
768
769 assert_non_null(tree);
770 assert_null(tree->schema);
771 assert_string_equal(((struct lyd_node_opaq *)tree)->name, "rpc-reply");
772 node = lyd_node_children(tree, 0);
773 assert_non_null(node->schema);
774 assert_string_equal(node->schema->name, "c");
775
776 /* TODO print only rpc-reply node and then output subtree */
777 lyd_print_tree(out, lyd_node_children(op, 0), LYD_JSON, 0);
778 assert_string_equal(str, "{\"a:al\":25}");
779 ly_out_reset(out);
780 lyd_print_tree(out, lyd_node_children(tree, 0), LYD_JSON, 0);
781 assert_string_equal(str, "{\"a:c\":{\"act\":{\"al\":25}}}");
782 ly_out_reset(out);
783 lyd_free_all(tree);
784
785 /* wrong namespace, element name, whatever... */
786 /* TODO */
787
788 ly_out_free(out, NULL, 1);
789
790 *state = NULL;
791}
792
793int main(void)
794{
795 const struct CMUnitTest tests[] = {
796 cmocka_unit_test_setup_teardown(test_leaf, setup, teardown),
797 cmocka_unit_test_setup_teardown(test_leaflist, setup, teardown),
798 cmocka_unit_test_setup_teardown(test_anydata, setup, teardown),
799 cmocka_unit_test_setup_teardown(test_list, setup, teardown),
800 cmocka_unit_test_setup_teardown(test_container, setup, teardown),
801 cmocka_unit_test_setup_teardown(test_opaq, setup, teardown),
802 cmocka_unit_test_setup_teardown(test_rpc, setup, teardown),
803 cmocka_unit_test_setup_teardown(test_action, setup, teardown),
804 cmocka_unit_test_setup_teardown(test_notification, setup, teardown),
805 cmocka_unit_test_setup_teardown(test_reply, setup, teardown),
806 };
807
808 return cmocka_run_group_tests(tests, NULL, NULL);
809}