blob: 74f5e3de93623a405977367ffdaa37c6a751c1fa [file] [log] [blame]
Radek Krejci36bac2b2018-09-19 11:15:29 +02001/*
2 * @file set.c
3 * @author: Radek Krejci <rkrejci@cesnet.cz>
4 * @brief unit tests for functions from common.c
5 *
6 * Copyright (c) 2018 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 Krejci36bac2b2018-09-19 11:15:29 +020015#include <stdarg.h>
16#include <stddef.h>
17#include <setjmp.h>
18#include <cmocka.h>
19
Radek Krejci2d7a47b2019-05-16 13:34:10 +020020#include "../../src/common.h"
Radek Krejci36bac2b2018-09-19 11:15:29 +020021
22#define BUFSIZE 1024
23char logbuf[BUFSIZE] = {0};
Radek Krejcib4a4a272019-06-10 12:44:52 +020024int store = -1; /* negative for infinite logging, positive for limited logging */
Radek Krejci36bac2b2018-09-19 11:15:29 +020025
Radek Krejcib4a4a272019-06-10 12:44:52 +020026/* set to 0 to printing error messages to stderr instead of checking them in code */
27#define ENABLE_LOGGER_CHECKING 1
28
29#if ENABLE_LOGGER_CHECKING
Radek Krejci36bac2b2018-09-19 11:15:29 +020030static void
31logger(LY_LOG_LEVEL level, const char *msg, const char *path)
32{
33 (void) level; /* unused */
Radek Krejcib4a4a272019-06-10 12:44:52 +020034 if (store) {
35 if (path && path[0]) {
36 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
37 } else {
38 strncpy(logbuf, msg, BUFSIZE - 1);
39 }
40 if (store > 0) {
41 --store;
42 }
43 }
Radek Krejci36bac2b2018-09-19 11:15:29 +020044}
Radek Krejcib4a4a272019-06-10 12:44:52 +020045#endif
Radek Krejci36bac2b2018-09-19 11:15:29 +020046
47static int
48logger_setup(void **state)
49{
50 (void) state; /* unused */
51
52 ly_set_log_clb(logger, 0);
53
54 return 0;
55}
56
Radek Krejcib4a4a272019-06-10 12:44:52 +020057static int
58logger_teardown(void **state)
59{
60 (void) state; /* unused */
61#if ENABLE_LOGGER_CHECKING
62 if (*state) {
63 fprintf(stderr, "%s\n", logbuf);
64 }
65#endif
66 return 0;
67}
68
69void
70logbuf_clean(void)
71{
72 logbuf[0] = '\0';
73}
74
75#if ENABLE_LOGGER_CHECKING
76# define logbuf_assert(str) assert_string_equal(logbuf, str)
77#else
78# define logbuf_assert(str)
79#endif
80
Radek Krejci36bac2b2018-09-19 11:15:29 +020081static void
Radek Krejci44ceedc2018-10-02 15:54:31 +020082test_utf8(void **state)
83{
84 (void) state; /* unused */
85
86 char buf[5] = {0};
87 const char *str = buf;
88 unsigned int c;
89 size_t len;
90
91 /* test invalid UTF-8 characters in lyxml_getutf8
92 * - https://en.wikipedia.org/wiki/UTF-8 */
93 buf[0] = 0x04;
94 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
95 buf[0] = 0x80;
96 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
97
98 buf[0] = 0xc0;
99 buf[1] = 0x00;
100 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
101 buf[1] = 0x80;
102 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
103
104 buf[0] = 0xe0;
105 buf[1] = 0x00;
106 buf[2] = 0x80;
107 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
108 buf[1] = 0x80;
109 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
110
111 buf[0] = 0xf0;
112 buf[1] = 0x00;
113 buf[2] = 0x80;
114 buf[3] = 0x80;
115 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
116 buf[1] = 0x80;
117 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
118}
119
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100120#ifndef APPLE
Radek Krejci36bac2b2018-09-19 11:15:29 +0200121void *__real_realloc(void *ptr, size_t size);
122void *__wrap_realloc(void *ptr, size_t size)
123{
124 int wrap = mock_type(int);
125
126 if (wrap) {
127 /* memory allocation failed */
128 return NULL;
129 } else {
130 return __real_realloc(ptr, size);
131 }
132}
133
134static void
135test_lyrealloc(void **state)
136{
137 (void) state; /* unused */
138
139 char *ptr;
140
141 ptr = malloc(1);
142 assert_non_null(ptr);
143
144 /* realloc */
145 will_return(__wrap_realloc, 0);
146 ptr = ly_realloc(ptr, 2048);
147 assert_non_null(ptr);
148 ptr[2047] = 0; /* test write */
149
150 /* realloc fails */
151 will_return(__wrap_realloc, 1);
152 ptr = ly_realloc(ptr, 2048);
153 assert_null(ptr);
154
155 /* ptr should be freed by ly_realloc() */
156}
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100157#endif /* not APPLE */
Radek Krejci36bac2b2018-09-19 11:15:29 +0200158
Radek Krejcib4a4a272019-06-10 12:44:52 +0200159static void
Radek Krejci9ea8ca12019-06-10 13:11:55 +0200160test_parse_int(void **state)
161{
162 *state = test_parse_int;
163 const char *str;
164 int64_t i = 500;
165
166 str = "10";
167 assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
168 assert_int_equal(i, 10);
169
170 /* leading zeros are allowed, trailing whitespaces are allowed */
171 str = "000\n\t ";
172 assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
173 assert_int_equal(i, 0);
174
175 /* negative value */
176 str = "-10";
177 assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
178 assert_int_equal(i, -10);
179
180 /* non-NULL terminated string */
181 str = "+5sometext";
182 assert_int_equal(LY_SUCCESS, ly_parse_int(str, 2, -10, 10, 10, &i));
183 assert_int_equal(i, 5);
184
185 /* out of bounds value */
186 str = "11";
187 assert_int_equal(LY_EDENIED, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
188 str = "-11";
189 assert_int_equal(LY_EDENIED, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
190
191 /* NaN */
192 str = "zero";
193 assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
194
195 /* mixing number with text */
196 str = "10zero";
197 assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
198
199 str = "10 zero";
200 assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
201
202 *state = NULL;
203}
204
205static void
206test_parse_uint(void **state)
207{
208 *state = test_parse_int;
209 const char *str;
210 uint64_t u = 500;
211
212 str = "10";
213 assert_int_equal(LY_SUCCESS, ly_parse_uint(str, strlen(str), 10, 10, &u));
214 assert_int_equal(u, 10);
215
216 /* leading zeros are allowed, trailing whitespaces are allowed */
217 str = "000\n\t ";
218 assert_int_equal(LY_SUCCESS, ly_parse_uint(str, strlen(str), 10, 10, &u));
219 assert_int_equal(u, 0);
220 /* non-NULL terminated string */
221 str = "+5sometext";
222 assert_int_equal(LY_SUCCESS, ly_parse_uint(str, 2, 10, 10, &u));
223 assert_int_equal(u, 5);
224
225 /* out of bounds value */
226 str = "11";
227 assert_int_equal(LY_EDENIED, ly_parse_uint(str, strlen(str), 10, 10, &u));
228 str = "-1";
229 assert_int_equal(LY_EDENIED, ly_parse_uint(str, strlen(str), (uint64_t)-1, 10, &u));
230
231 /* NaN */
232 str = "zero";
233 assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
234
235 /* mixing number with text */
236 str = "10zero";
237 assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
238
239 str = "10 zero";
240 assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
241
242 *state = NULL;
243}
244
245static void
Radek Krejcib4a4a272019-06-10 12:44:52 +0200246test_parse_nodeid(void **state)
247{
Radek Krejci10bfdf82019-06-10 14:08:13 +0200248 *state = test_parse_nodeid;
Radek Krejcib4a4a272019-06-10 12:44:52 +0200249 const char *str;
250 const char *prefix, *name;
251 size_t prefix_len, name_len;
252
253 str = "123";
254 assert_int_equal(LY_EINVAL, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
255
256 str = "a12_-.!";
257 assert_int_equal(LY_SUCCESS, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
258 assert_null(prefix);
259 assert_int_equal(0, prefix_len);
260 assert_non_null(name);
261 assert_int_equal(6, name_len);
262 assert_int_equal(0, strncmp("a12_-.", name, name_len));
263 assert_string_equal("!", str);
264
265 str = "a12_-.:_b2 xxx";
266 assert_int_equal(LY_SUCCESS, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
267 assert_non_null(prefix);
268 assert_int_equal(6, prefix_len);
269 assert_int_equal(0, strncmp("a12_-.", prefix, prefix_len));
270 assert_non_null(name);
271 assert_int_equal(3, name_len);
272 assert_int_equal(0, strncmp("_b2", name, name_len));
273 assert_string_equal(" xxx", str);
Radek Krejci10bfdf82019-06-10 14:08:13 +0200274
275 *state = NULL;
276}
277
278static void
279test_parse_instance_predicate(void **state)
280{
281 *state = test_parse_instance_predicate;
282 const char *str, *errmsg;
283 const char *prefix, *id, *value;
284 size_t prefix_len, id_len, value_len;
285
286 str = "[ex:name='fred']";
Radek Krejci084289f2019-07-09 17:35:30 +0200287 assert_int_equal(LY_SUCCESS, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200288 assert_string_equal(str, "");
289 assert_string_equal(prefix, "ex:name='fred']");
290 assert_int_equal(prefix_len, 2);
291 assert_string_equal(id, "name='fred']");
292 assert_int_equal(id_len, 4);
293 assert_string_equal(value, "fred']");
294 assert_int_equal(value_len, 4);
295
296 str = "[ex:ip = \"[192.0.2.1]\"][ex:port='80']";
Radek Krejci084289f2019-07-09 17:35:30 +0200297 assert_int_equal(LY_SUCCESS, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200298 assert_string_equal(str, "[ex:port='80']");
299 assert_string_equal(prefix, "ex:ip = \"[192.0.2.1]\"][ex:port='80']");
300 assert_int_equal(prefix_len, 2);
301 assert_string_equal(id, "ip = \"[192.0.2.1]\"][ex:port='80']");
302 assert_int_equal(id_len, 2);
303 assert_string_equal(value, "[192.0.2.1]\"][ex:port='80']");
304 assert_int_equal(value_len, 11);
305
306 str = "[. = 'blowfish-cbc']";
Radek Krejci084289f2019-07-09 17:35:30 +0200307 assert_int_equal(LY_SUCCESS, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200308 assert_string_equal(str, "");
309 assert_null(prefix);
310 assert_int_equal(prefix_len, 0);
311 assert_string_equal(id, ". = 'blowfish-cbc']");
312 assert_int_equal(id_len, 1);
313 assert_string_equal(value, "blowfish-cbc']");
314 assert_int_equal(value_len, 12);
315
316 str = "[ 3 ]";
Radek Krejci084289f2019-07-09 17:35:30 +0200317 assert_int_equal(LY_SUCCESS, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200318 assert_string_equal(str, "");
319 assert_null(prefix);
320 assert_int_equal(prefix_len, 0);
321 assert_null(id);
322 assert_int_equal(id_len, 0);
323 assert_string_equal(value, "3 ]");
324 assert_int_equal(value_len, 1);
325
326 /* invalid predicates */
327 /* position must be positive integer */
328 str = "[0]";
Radek Krejci084289f2019-07-09 17:35:30 +0200329 assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200330 assert_string_equal(errmsg, "The position predicate cannot be zero.");
331 str = "[-1]";
Radek Krejci084289f2019-07-09 17:35:30 +0200332 assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200333 assert_string_equal(errmsg, "Invalid instance predicate format (negative position or invalid node-identifier).");
334
335 /* invalid node-identifier */
336 str = "[$node='value']";
Radek Krejci084289f2019-07-09 17:35:30 +0200337 assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200338 assert_string_equal(errmsg, "Invalid node-identifier.");
339 str = "[.node='value']";
Radek Krejci084289f2019-07-09 17:35:30 +0200340 assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200341 assert_string_equal(errmsg, "Unexpected character instead of '=' in leaf-list-predicate.");
342 str = "[13node='value']";
Radek Krejci084289f2019-07-09 17:35:30 +0200343 assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200344 assert_string_equal(errmsg, "Predicate (pos) is not terminated by \']\' character.");
345
Radek Krejci084289f2019-07-09 17:35:30 +0200346 str = "[ex:node]";
347 assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200348 assert_string_equal(errmsg, "Unexpected character instead of '=' in key-predicate.");
349
Radek Krejci084289f2019-07-09 17:35:30 +0200350 str = "[ex:node= value]";
351 assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200352 assert_string_equal(errmsg, "String value is not quoted.");
353
Radek Krejci084289f2019-07-09 17:35:30 +0200354 str = "[ex:node='value\"]";
355 assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200356 assert_string_equal(errmsg, "Value is not terminated quoted-string.");
357
Radek Krejci084289f2019-07-09 17:35:30 +0200358 str = "[ex:node='value ]";
359 assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200360 assert_string_equal(errmsg, "Value is not terminated quoted-string.");
361
Radek Krejci084289f2019-07-09 17:35:30 +0200362 str = "[ex:node=\"value\"[3]";
363 assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200364 assert_string_equal(errmsg, "Predicate (key-predicate) is not terminated by \']\' character.");
365 str = "[.=\"value\"[3]";
Radek Krejci084289f2019-07-09 17:35:30 +0200366 assert_int_equal(LY_EVALID, ly_parse_instance_predicate(&str, strlen(str), LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200367 assert_string_equal(errmsg, "Predicate (leaf-list-predicate) is not terminated by \']\' character.");
368
Radek Krejci084289f2019-07-09 17:35:30 +0200369 /* the limit of the string is too short, it ends one character earlier */
370 str = "[ex:node='value']";
371 assert_int_equal(LY_EINVAL, ly_parse_instance_predicate(&str, strlen(str) - 1, LYD_XML, &prefix, &prefix_len, &id, &id_len, &value, &value_len, &errmsg));
Radek Krejci10bfdf82019-06-10 14:08:13 +0200372 assert_string_equal(errmsg, "Predicate is incomplete.");
373
374 *state = NULL;
Radek Krejcib4a4a272019-06-10 12:44:52 +0200375}
376
Radek Krejci36bac2b2018-09-19 11:15:29 +0200377int main(void)
378{
379 const struct CMUnitTest tests[] = {
Radek Krejcib4a4a272019-06-10 12:44:52 +0200380 cmocka_unit_test_setup_teardown(test_utf8, logger_setup, logger_teardown),
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100381#ifndef APPLE
Radek Krejci36bac2b2018-09-19 11:15:29 +0200382 cmocka_unit_test(test_lyrealloc),
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100383#endif
Radek Krejci9ea8ca12019-06-10 13:11:55 +0200384 cmocka_unit_test_setup_teardown(test_parse_int, logger_setup, logger_teardown),
385 cmocka_unit_test_setup_teardown(test_parse_uint, logger_setup, logger_teardown),
Radek Krejcib4a4a272019-06-10 12:44:52 +0200386 cmocka_unit_test_setup_teardown(test_parse_nodeid, logger_setup, logger_teardown),
Radek Krejci10bfdf82019-06-10 14:08:13 +0200387 cmocka_unit_test_setup_teardown(test_parse_instance_predicate, logger_setup, logger_teardown),
Radek Krejci36bac2b2018-09-19 11:15:29 +0200388 };
389
390 return cmocka_run_group_tests(tests, NULL, NULL);
391}