blob: 0984e1e1c630adc2d26fdeb065b4c68ebb8342fe [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 Krejcica376bd2020-06-11 16:04:06 +020015
16
Radek Krejci36bac2b2018-09-19 11:15:29 +020017#include <stdarg.h>
18#include <stddef.h>
19#include <setjmp.h>
20#include <cmocka.h>
21
Radek Krejcica376bd2020-06-11 16:04:06 +020022#include <string.h>
23#include <stdlib.h>
24#include <stdio.h>
25
Radek Krejci2d7a47b2019-05-16 13:34:10 +020026#include "../../src/common.h"
Radek Krejci36bac2b2018-09-19 11:15:29 +020027
28#define BUFSIZE 1024
29char logbuf[BUFSIZE] = {0};
Radek Krejcib4a4a272019-06-10 12:44:52 +020030int store = -1; /* negative for infinite logging, positive for limited logging */
Radek Krejci36bac2b2018-09-19 11:15:29 +020031
Radek Krejcib4a4a272019-06-10 12:44:52 +020032/* set to 0 to printing error messages to stderr instead of checking them in code */
33#define ENABLE_LOGGER_CHECKING 1
34
35#if ENABLE_LOGGER_CHECKING
Radek Krejci36bac2b2018-09-19 11:15:29 +020036static void
37logger(LY_LOG_LEVEL level, const char *msg, const char *path)
38{
39 (void) level; /* unused */
Radek Krejcib4a4a272019-06-10 12:44:52 +020040 if (store) {
41 if (path && path[0]) {
42 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
43 } else {
44 strncpy(logbuf, msg, BUFSIZE - 1);
45 }
46 if (store > 0) {
47 --store;
48 }
49 }
Radek Krejci36bac2b2018-09-19 11:15:29 +020050}
Radek Krejcib4a4a272019-06-10 12:44:52 +020051#endif
Radek Krejci36bac2b2018-09-19 11:15:29 +020052
53static int
54logger_setup(void **state)
55{
56 (void) state; /* unused */
57
58 ly_set_log_clb(logger, 0);
59
60 return 0;
61}
62
Radek Krejcib4a4a272019-06-10 12:44:52 +020063static int
64logger_teardown(void **state)
65{
66 (void) state; /* unused */
67#if ENABLE_LOGGER_CHECKING
68 if (*state) {
69 fprintf(stderr, "%s\n", logbuf);
70 }
71#endif
72 return 0;
73}
74
75void
76logbuf_clean(void)
77{
78 logbuf[0] = '\0';
79}
80
81#if ENABLE_LOGGER_CHECKING
82# define logbuf_assert(str) assert_string_equal(logbuf, str)
83#else
84# define logbuf_assert(str)
85#endif
86
Radek Krejci36bac2b2018-09-19 11:15:29 +020087static void
Radek Krejci44ceedc2018-10-02 15:54:31 +020088test_utf8(void **state)
89{
90 (void) state; /* unused */
91
92 char buf[5] = {0};
93 const char *str = buf;
94 unsigned int c;
95 size_t len;
96
97 /* test invalid UTF-8 characters in lyxml_getutf8
98 * - https://en.wikipedia.org/wiki/UTF-8 */
99 buf[0] = 0x04;
100 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
101 buf[0] = 0x80;
102 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
103
104 buf[0] = 0xc0;
105 buf[1] = 0x00;
106 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
107 buf[1] = 0x80;
108 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
109
110 buf[0] = 0xe0;
111 buf[1] = 0x00;
112 buf[2] = 0x80;
113 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
114 buf[1] = 0x80;
115 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
116
117 buf[0] = 0xf0;
118 buf[1] = 0x00;
119 buf[2] = 0x80;
120 buf[3] = 0x80;
121 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
122 buf[1] = 0x80;
123 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
124}
125
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100126#ifndef APPLE
Radek Krejci36bac2b2018-09-19 11:15:29 +0200127void *__real_realloc(void *ptr, size_t size);
128void *__wrap_realloc(void *ptr, size_t size)
129{
130 int wrap = mock_type(int);
131
132 if (wrap) {
133 /* memory allocation failed */
134 return NULL;
135 } else {
136 return __real_realloc(ptr, size);
137 }
138}
139
140static void
141test_lyrealloc(void **state)
142{
143 (void) state; /* unused */
144
145 char *ptr;
146
147 ptr = malloc(1);
148 assert_non_null(ptr);
149
150 /* realloc */
151 will_return(__wrap_realloc, 0);
152 ptr = ly_realloc(ptr, 2048);
153 assert_non_null(ptr);
154 ptr[2047] = 0; /* test write */
155
156 /* realloc fails */
157 will_return(__wrap_realloc, 1);
158 ptr = ly_realloc(ptr, 2048);
159 assert_null(ptr);
160
161 /* ptr should be freed by ly_realloc() */
162}
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100163#endif /* not APPLE */
Radek Krejci36bac2b2018-09-19 11:15:29 +0200164
Radek Krejcib4a4a272019-06-10 12:44:52 +0200165static void
Radek Krejci9ea8ca12019-06-10 13:11:55 +0200166test_parse_int(void **state)
167{
168 *state = test_parse_int;
169 const char *str;
170 int64_t i = 500;
171
172 str = "10";
173 assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
174 assert_int_equal(i, 10);
175
176 /* leading zeros are allowed, trailing whitespaces are allowed */
177 str = "000\n\t ";
178 assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
179 assert_int_equal(i, 0);
180
181 /* negative value */
182 str = "-10";
183 assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
184 assert_int_equal(i, -10);
185
186 /* non-NULL terminated string */
187 str = "+5sometext";
188 assert_int_equal(LY_SUCCESS, ly_parse_int(str, 2, -10, 10, 10, &i));
189 assert_int_equal(i, 5);
190
191 /* out of bounds value */
192 str = "11";
193 assert_int_equal(LY_EDENIED, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
194 str = "-11";
195 assert_int_equal(LY_EDENIED, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
196
197 /* NaN */
198 str = "zero";
199 assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
200
201 /* mixing number with text */
202 str = "10zero";
203 assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
204
205 str = "10 zero";
206 assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
207
208 *state = NULL;
209}
210
211static void
212test_parse_uint(void **state)
213{
214 *state = test_parse_int;
215 const char *str;
216 uint64_t u = 500;
217
218 str = "10";
219 assert_int_equal(LY_SUCCESS, ly_parse_uint(str, strlen(str), 10, 10, &u));
220 assert_int_equal(u, 10);
221
222 /* leading zeros are allowed, trailing whitespaces are allowed */
223 str = "000\n\t ";
224 assert_int_equal(LY_SUCCESS, ly_parse_uint(str, strlen(str), 10, 10, &u));
225 assert_int_equal(u, 0);
226 /* non-NULL terminated string */
227 str = "+5sometext";
228 assert_int_equal(LY_SUCCESS, ly_parse_uint(str, 2, 10, 10, &u));
229 assert_int_equal(u, 5);
230
231 /* out of bounds value */
232 str = "11";
233 assert_int_equal(LY_EDENIED, ly_parse_uint(str, strlen(str), 10, 10, &u));
234 str = "-1";
235 assert_int_equal(LY_EDENIED, ly_parse_uint(str, strlen(str), (uint64_t)-1, 10, &u));
236
237 /* NaN */
238 str = "zero";
239 assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
240
241 /* mixing number with text */
242 str = "10zero";
243 assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
244
245 str = "10 zero";
246 assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
247
248 *state = NULL;
249}
250
251static void
Radek Krejcib4a4a272019-06-10 12:44:52 +0200252test_parse_nodeid(void **state)
253{
Radek Krejci10bfdf82019-06-10 14:08:13 +0200254 *state = test_parse_nodeid;
Radek Krejcib4a4a272019-06-10 12:44:52 +0200255 const char *str;
256 const char *prefix, *name;
257 size_t prefix_len, name_len;
258
259 str = "123";
260 assert_int_equal(LY_EINVAL, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
261
262 str = "a12_-.!";
263 assert_int_equal(LY_SUCCESS, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
264 assert_null(prefix);
265 assert_int_equal(0, prefix_len);
266 assert_non_null(name);
267 assert_int_equal(6, name_len);
268 assert_int_equal(0, strncmp("a12_-.", name, name_len));
269 assert_string_equal("!", str);
270
271 str = "a12_-.:_b2 xxx";
272 assert_int_equal(LY_SUCCESS, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
273 assert_non_null(prefix);
274 assert_int_equal(6, prefix_len);
275 assert_int_equal(0, strncmp("a12_-.", prefix, prefix_len));
276 assert_non_null(name);
277 assert_int_equal(3, name_len);
278 assert_int_equal(0, strncmp("_b2", name, name_len));
279 assert_string_equal(" xxx", str);
Radek Krejci10bfdf82019-06-10 14:08:13 +0200280
281 *state = NULL;
282}
283
284static void
285test_parse_instance_predicate(void **state)
286{
287 *state = test_parse_instance_predicate;
288 const char *str, *errmsg;
289 const char *prefix, *id, *value;
290 size_t prefix_len, id_len, value_len;
291
292 str = "[ex:name='fred']";
Radek Krejci084289f2019-07-09 17:35:30 +0200293 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 +0200294 assert_string_equal(str, "");
295 assert_string_equal(prefix, "ex:name='fred']");
296 assert_int_equal(prefix_len, 2);
297 assert_string_equal(id, "name='fred']");
298 assert_int_equal(id_len, 4);
299 assert_string_equal(value, "fred']");
300 assert_int_equal(value_len, 4);
301
302 str = "[ex:ip = \"[192.0.2.1]\"][ex:port='80']";
Radek Krejci084289f2019-07-09 17:35:30 +0200303 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 +0200304 assert_string_equal(str, "[ex:port='80']");
305 assert_string_equal(prefix, "ex:ip = \"[192.0.2.1]\"][ex:port='80']");
306 assert_int_equal(prefix_len, 2);
307 assert_string_equal(id, "ip = \"[192.0.2.1]\"][ex:port='80']");
308 assert_int_equal(id_len, 2);
309 assert_string_equal(value, "[192.0.2.1]\"][ex:port='80']");
310 assert_int_equal(value_len, 11);
311
312 str = "[. = 'blowfish-cbc']";
Radek Krejci084289f2019-07-09 17:35:30 +0200313 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 +0200314 assert_string_equal(str, "");
315 assert_null(prefix);
316 assert_int_equal(prefix_len, 0);
317 assert_string_equal(id, ". = 'blowfish-cbc']");
318 assert_int_equal(id_len, 1);
319 assert_string_equal(value, "blowfish-cbc']");
320 assert_int_equal(value_len, 12);
321
322 str = "[ 3 ]";
Radek Krejci084289f2019-07-09 17:35:30 +0200323 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 +0200324 assert_string_equal(str, "");
325 assert_null(prefix);
326 assert_int_equal(prefix_len, 0);
327 assert_null(id);
328 assert_int_equal(id_len, 0);
329 assert_string_equal(value, "3 ]");
330 assert_int_equal(value_len, 1);
331
332 /* invalid predicates */
333 /* position must be positive integer */
334 str = "[0]";
Radek Krejci084289f2019-07-09 17:35:30 +0200335 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 +0200336 assert_string_equal(errmsg, "The position predicate cannot be zero.");
337 str = "[-1]";
Radek Krejci084289f2019-07-09 17:35:30 +0200338 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 +0200339 assert_string_equal(errmsg, "Invalid instance predicate format (negative position or invalid node-identifier).");
340
341 /* invalid node-identifier */
342 str = "[$node='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, "Invalid node-identifier.");
345 str = "[.node='value']";
Radek Krejci084289f2019-07-09 17:35:30 +0200346 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 +0200347 assert_string_equal(errmsg, "Unexpected character instead of '=' in leaf-list-predicate.");
348 str = "[13node='value']";
Radek Krejci084289f2019-07-09 17:35:30 +0200349 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 +0200350 assert_string_equal(errmsg, "Predicate (pos) is not terminated by \']\' character.");
351
Radek Krejci084289f2019-07-09 17:35:30 +0200352 str = "[ex:node]";
353 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 +0200354 assert_string_equal(errmsg, "Unexpected character instead of '=' in key-predicate.");
355
Radek Krejci084289f2019-07-09 17:35:30 +0200356 str = "[ex:node= value]";
357 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 +0200358 assert_string_equal(errmsg, "String value is not quoted.");
359
Radek Krejci084289f2019-07-09 17:35:30 +0200360 str = "[ex:node='value\"]";
361 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 +0200362 assert_string_equal(errmsg, "Value is not terminated quoted-string.");
363
Radek Krejci084289f2019-07-09 17:35:30 +0200364 str = "[ex:node='value ]";
365 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 +0200366 assert_string_equal(errmsg, "Value is not terminated quoted-string.");
367
Radek Krejci084289f2019-07-09 17:35:30 +0200368 str = "[ex:node=\"value\"[3]";
369 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 +0200370 assert_string_equal(errmsg, "Predicate (key-predicate) is not terminated by \']\' character.");
371 str = "[.=\"value\"[3]";
Radek Krejci084289f2019-07-09 17:35:30 +0200372 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 +0200373 assert_string_equal(errmsg, "Predicate (leaf-list-predicate) is not terminated by \']\' character.");
374
Radek Krejci084289f2019-07-09 17:35:30 +0200375 /* the limit of the string is too short, it ends one character earlier */
376 str = "[ex:node='value']";
377 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 +0200378 assert_string_equal(errmsg, "Predicate is incomplete.");
379
380 *state = NULL;
Radek Krejcib4a4a272019-06-10 12:44:52 +0200381}
382
Radek Krejci36bac2b2018-09-19 11:15:29 +0200383int main(void)
384{
385 const struct CMUnitTest tests[] = {
Radek Krejcib4a4a272019-06-10 12:44:52 +0200386 cmocka_unit_test_setup_teardown(test_utf8, logger_setup, logger_teardown),
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100387#ifndef APPLE
Radek Krejci36bac2b2018-09-19 11:15:29 +0200388 cmocka_unit_test(test_lyrealloc),
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100389#endif
Radek Krejci9ea8ca12019-06-10 13:11:55 +0200390 cmocka_unit_test_setup_teardown(test_parse_int, logger_setup, logger_teardown),
391 cmocka_unit_test_setup_teardown(test_parse_uint, logger_setup, logger_teardown),
Radek Krejcib4a4a272019-06-10 12:44:52 +0200392 cmocka_unit_test_setup_teardown(test_parse_nodeid, logger_setup, logger_teardown),
Radek Krejci10bfdf82019-06-10 14:08:13 +0200393 cmocka_unit_test_setup_teardown(test_parse_instance_predicate, logger_setup, logger_teardown),
Radek Krejci36bac2b2018-09-19 11:15:29 +0200394 };
395
396 return cmocka_run_group_tests(tests, NULL, NULL);
397}