blob: 942f5b9dd4d725d07933448bb7e7419dbedf07aa [file] [log] [blame]
Radek Krejci26a5dfb2019-07-26 14:51:06 +02001/*
2 * @file test_printer_xml.c
3 * @author: Radek Krejci <rkrejci@cesnet.cz>
4 * @brief unit tests for functions from printer_yang.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 "../../src/context.h"
24#include "../../src/printer_data.h"
25
26#define BUFSIZE 1024
27char logbuf[BUFSIZE] = {0};
28int store = -1; /* negative for infinite logging, positive for limited logging */
29
30struct state_s {
31 void *func;
32 struct ly_ctx *ctx;
33};
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 struct state_s *s;
60 const char *schema_a = "module defs {namespace urn:tests:defs;prefix d;yang-version 1.1;"
61 "identity crypto-alg; identity interface-type; identity ethernet {base interface-type;} identity fast-ethernet {base ethernet;}}";
62 const char *schema_b = "module types {namespace urn:tests:types;prefix t;yang-version 1.1; import defs {prefix defs;}"
63 "feature f; identity gigabit-ethernet { base defs:ethernet;}"
64 "container cont {leaf leaftarget {type empty;}"
65 "list listtarget {key id; max-elements 5;leaf id {type uint8;} leaf value {type string;}"
66 "action test {input {leaf a {type string;}} output {leaf b {type string;}}}}"
67 "leaf-list leaflisttarget {type uint8; max-elements 5;}}"
68 "list list {key id; leaf id {type string;} leaf value {type string;} leaf-list targets {type string;}}"
69 "list list2 {key \"id value\"; leaf id {type string;} leaf value {type string;}}"
70 "list list_inst {key id; leaf id {type instance-identifier {require-instance true;}} leaf value {type string;}}"
71 "list list_ident {key id; leaf id {type identityref {base defs:interface-type;}} leaf value {type string;}}"
72 "leaf-list leaflisttarget {type string;}"
73 "leaf binary {type binary {length 5 {error-message \"This base64 value must be of length 5.\";}}}"
74 "leaf binary-norestr {type binary;}"
75 "leaf int8 {type int8 {range 10..20;}}"
76 "leaf uint8 {type uint8 {range 150..200;}}"
77 "leaf int16 {type int16 {range -20..-10;}}"
78 "leaf uint16 {type uint16 {range 150..200;}}"
79 "leaf int32 {type int32;}"
80 "leaf uint32 {type uint32;}"
81 "leaf int64 {type int64;}"
82 "leaf uint64 {type uint64;}"
83 "leaf bits {type bits {bit zero; bit one {if-feature f;} bit two;}}"
84 "leaf enums {type enumeration {enum white; enum yellow {if-feature f;}}}"
85 "leaf dec64 {type decimal64 {fraction-digits 1; range 1.5..10;}}"
86 "leaf dec64-norestr {type decimal64 {fraction-digits 18;}}"
87 "leaf str {type string {length 8..10; pattern '[a-z ]*';}}"
88 "leaf str-norestr {type string;}"
89 "leaf bool {type boolean;}"
90 "leaf empty {type empty;}"
91 "leaf ident {type identityref {base defs:interface-type;}}"
92 "leaf inst {type instance-identifier {require-instance true;}}"
93 "leaf inst-noreq {type instance-identifier {require-instance false;}}"
94 "leaf lref {type leafref {path /leaflisttarget; require-instance true;}}"
95 "leaf lref2 {type leafref {path \"../list[id = current()/../str-norestr]/targets\"; require-instance true;}}"
96 "leaf un1 {type union {"
97 "type leafref {path /int8; require-instance true;}"
98 "type union { type identityref {base defs:interface-type;} type instance-identifier {require-instance true;} }"
99 "type string {length 1..20;}}}"
100 "anydata any;"
101 "rpc sum {input {leaf x {type uint8;} leaf y {type uint8;}} output {leaf result {type uint16;}}}}";
102
103 s = calloc(1, sizeof *s);
104 assert_non_null(s);
105
106#if ENABLE_LOGGER_CHECKING
107 ly_set_log_clb(logger, 1);
108#endif
109
110 assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &s->ctx));
111 assert_non_null(lys_parse_mem(s->ctx, schema_a, LYS_IN_YANG));
112 assert_non_null(lys_parse_mem(s->ctx, schema_b, LYS_IN_YANG));
113
114 *state = s;
115
116 return 0;
117}
118
119static int
120teardown(void **state)
121{
122 struct state_s *s = (struct state_s*)(*state);
123
124#if ENABLE_LOGGER_CHECKING
125 if (s->func) {
126 fprintf(stderr, "%s\n", logbuf);
127 }
128#endif
129
130 ly_ctx_destroy(s->ctx, NULL);
131 free(s);
132
133 return 0;
134}
135
136void
137logbuf_clean(void)
138{
139 logbuf[0] = '\0';
140}
141
142#if ENABLE_LOGGER_CHECKING
143# define logbuf_assert(str) assert_string_equal(logbuf, str)
144#else
145# define logbuf_assert(str)
146#endif
147
148static void
149test_leaf(void **state)
150{
151 struct state_s *s = (struct state_s*)(*state);
152 struct lyd_node *tree;
153 const char *data;
154 const char *result;
155 char *printed;
156 ssize_t len;
157
158 s->func = test_leaf;
159
160 data = "<int8 xmlns=\"urn:tests:types\">\n 15 \t\n </int8>";
161 result = "<int8 xmlns=\"urn:tests:types\">15</int8>";
162 assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_OPT_DATA, NULL));
163 assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, 0)) >= 0);
164 assert_int_equal(len, strlen(printed));
165 assert_string_equal(printed, result);
166 free(printed);
167 lyd_free_all(tree);
168
169 s->func = NULL;
170}
171
172static void
173test_anydata(void **state)
174{
175 struct state_s *s = (struct state_s*)(*state);
176 struct lyd_node *tree;
177 const char *data;
178 char *printed;
179 ssize_t len;
180
181 s->func = test_anydata;
182
183 data = "<any xmlns=\"urn:tests:types\"><somexml xmlns:x=\"url:x\" xmlns=\"example.com\"><x:x/></somexml></any>";
184 assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_OPT_DATA, NULL));
185 assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, 0)) >= 0);
186 assert_int_equal(len, strlen(printed));
187 assert_string_equal(printed, data);
188 free(printed);
189 lyd_free_all(tree);
190
191 data = "<any xmlns=\"urn:tests:types\"/>";
192 assert_non_null(tree = lyd_parse_mem(s->ctx, data, LYD_XML, LYD_OPT_DATA, NULL));
193 assert_true((len = lyd_print_mem(&printed, tree, LYD_XML, 0)) >= 0);
194 assert_int_equal(len, strlen(printed));
195 assert_string_equal(printed, data);
196 free(printed);
197 lyd_free_all(tree);
198
199 s->func = NULL;
200}
201
202static void
203test_rpc(void **state)
204{
205 struct state_s *s = (struct state_s*)(*state);
206 struct lyd_node *tree1;
207 struct lyd_node *tree2;
208 const struct lyd_node **trees;
209 const char *request;
210 const char *reply, *result;
211 char *printed;
212 ssize_t len;
213
214 s->func = test_rpc;
215
216 request = "<sum xmlns=\"urn:tests:types\"><x>10</x><y>20</y></sum>";
217 reply = "<result xmlns=\"urn:tests:types\">30</result>";
218 result = "<sum xmlns=\"urn:tests:types\"><result>30</result></sum>";
219 assert_non_null(tree1 = lyd_parse_mem(s->ctx, request, LYD_XML, LYD_OPT_RPC, NULL));
220 assert_true((len = lyd_print_mem(&printed, tree1, LYD_XML, 0)) >= 0);
221 assert_int_equal(len, strlen(printed));
222 assert_string_equal(printed, request);
223 free(printed);
224 assert_non_null(trees = lyd_trees_new(1, tree1));
225 assert_non_null(tree2 = lyd_parse_mem(s->ctx, reply, LYD_XML, LYD_OPT_RPCREPLY, trees));
226 assert_true((len = lyd_print_mem(&printed, tree2, LYD_XML, 0)) >= 0);
227 assert_int_equal(len, strlen(printed));
228 assert_string_equal(printed, result);
229 free(printed);
230 lyd_trees_free(trees, 0);
231 lyd_free_all(tree1);
232 lyd_free_all(tree2);
233
234 /* no arguments */
235 request = "<sum xmlns=\"urn:tests:types\"/>";
236 reply = "";
237 result = "<sum xmlns=\"urn:tests:types\"/>";
238 assert_non_null(tree1 = lyd_parse_mem(s->ctx, request, LYD_XML, LYD_OPT_RPC, NULL));
239 assert_true((len = lyd_print_mem(&printed, tree1, LYD_XML, 0)) >= 0);
240 assert_int_equal(len, strlen(printed));
241 assert_string_equal(printed, request);
242 free(printed);
243 assert_non_null(trees = lyd_trees_new(1, tree1));
244 assert_non_null(tree2 = lyd_parse_mem(s->ctx, reply, LYD_XML, LYD_OPT_RPCREPLY, trees));
245 assert_true((len = lyd_print_mem(&printed, tree2, LYD_XML, 0)) >= 0);
246 assert_int_equal(len, strlen(printed));
247 assert_string_equal(printed, result);
248 free(printed);
249 lyd_trees_free(trees, 0);
250 lyd_free_all(tree1);
251 lyd_free_all(tree2);
252
253 /* action
254 * "container cont {leaf leaftarget {type empty;}"
255 "list listtarget {key id; max-elements 5;leaf id {type uint8;} leaf value {type string;}"
256 "action test {input {leaf a {type string;}} output {leaf b {type string;}}}}"
257 "leaf-list leaflisttarget {type uint8; max-elements 5;}}"
258 */
259 request = "<cont xmlns=\"urn:tests:types\"><listtarget><id>10</id><test><a>test</a></test></listtarget></cont>";
260 reply = "<b xmlns=\"urn:tests:types\">test-reply</b>";
261 result = "<cont xmlns=\"urn:tests:types\"><listtarget><id>10</id><test><b>test-reply</b></test></listtarget></cont>";;
262 assert_non_null(tree1 = lyd_parse_mem(s->ctx, request, LYD_XML, LYD_OPT_RPC, NULL));
263 assert_true((len = lyd_print_mem(&printed, tree1, LYD_XML, 0)) >= 0);
264 assert_int_equal(len, strlen(printed));
265 assert_string_equal(printed, request);
266 free(printed);
267 assert_non_null(trees = lyd_trees_new(1, tree1));
268 assert_non_null(tree2 = lyd_parse_mem(s->ctx, reply, LYD_XML, LYD_OPT_RPCREPLY, trees));
269 assert_true((len = lyd_print_mem(&printed, tree2, LYD_XML, 0)) >= 0);
270 assert_int_equal(len, strlen(printed));
271 assert_string_equal(printed, result);
272 free(printed);
273 lyd_trees_free(trees, 0);
274 lyd_free_all(tree1);
275 lyd_free_all(tree2);
276
277 s->func = NULL;
278}
279
280int main(void)
281{
282 const struct CMUnitTest tests[] = {
283 cmocka_unit_test_setup_teardown(test_leaf, setup, teardown),
284 cmocka_unit_test_setup_teardown(test_anydata, setup, teardown),
285 cmocka_unit_test_setup_teardown(test_rpc, setup, teardown),
286 };
287
288 return cmocka_run_group_tests(tests, NULL, NULL);
289}