blob: 0c1012da0f97e4d143e6fa9caa0a919ee387aa8b [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#include <stdlib.h>
Radek Krejcica376bd2020-06-11 16:04:06 +020016
Radek Krejci70593c12020-06-13 20:48:09 +020017#include "common.h"
Radek Krejcib4ac5a92020-11-23 17:54:33 +010018#include "utests.h"
Radek Krejci36bac2b2018-09-19 11:15:29 +020019
20#define BUFSIZE 1024
21char logbuf[BUFSIZE] = {0};
Radek Krejcib4a4a272019-06-10 12:44:52 +020022int store = -1; /* negative for infinite logging, positive for limited logging */
Radek Krejci36bac2b2018-09-19 11:15:29 +020023
Radek Krejcib4a4a272019-06-10 12:44:52 +020024/* set to 0 to printing error messages to stderr instead of checking them in code */
25#define ENABLE_LOGGER_CHECKING 1
26
27#if ENABLE_LOGGER_CHECKING
Radek Krejci36bac2b2018-09-19 11:15:29 +020028static void
29logger(LY_LOG_LEVEL level, const char *msg, const char *path)
30{
31 (void) level; /* unused */
Radek Krejcib4a4a272019-06-10 12:44:52 +020032 if (store) {
33 if (path && path[0]) {
34 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
35 } else {
36 strncpy(logbuf, msg, BUFSIZE - 1);
37 }
38 if (store > 0) {
39 --store;
40 }
41 }
Radek Krejci36bac2b2018-09-19 11:15:29 +020042}
Radek Krejcib4ac5a92020-11-23 17:54:33 +010043
Radek Krejcib4a4a272019-06-10 12:44:52 +020044#endif
Radek Krejci36bac2b2018-09-19 11:15:29 +020045
46static int
47logger_setup(void **state)
48{
49 (void) state; /* unused */
50
51 ly_set_log_clb(logger, 0);
52
53 return 0;
54}
55
Radek Krejcib4a4a272019-06-10 12:44:52 +020056static int
57logger_teardown(void **state)
58{
59 (void) state; /* unused */
60#if ENABLE_LOGGER_CHECKING
61 if (*state) {
62 fprintf(stderr, "%s\n", logbuf);
63 }
64#endif
65 return 0;
66}
67
68void
69logbuf_clean(void)
70{
71 logbuf[0] = '\0';
72}
73
74#if ENABLE_LOGGER_CHECKING
75# define logbuf_assert(str) assert_string_equal(logbuf, str)
76#else
77# define logbuf_assert(str)
78#endif
79
Radek Krejci36bac2b2018-09-19 11:15:29 +020080static void
Radek Krejci44ceedc2018-10-02 15:54:31 +020081test_utf8(void **state)
82{
83 (void) state; /* unused */
84
85 char buf[5] = {0};
86 const char *str = buf;
87 unsigned int c;
88 size_t len;
89
90 /* test invalid UTF-8 characters in lyxml_getutf8
91 * - https://en.wikipedia.org/wiki/UTF-8 */
92 buf[0] = 0x04;
93 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
94 buf[0] = 0x80;
95 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
96
97 buf[0] = 0xc0;
98 buf[1] = 0x00;
99 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
100 buf[1] = 0x80;
101 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
102
103 buf[0] = 0xe0;
104 buf[1] = 0x00;
105 buf[2] = 0x80;
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] = 0xf0;
111 buf[1] = 0x00;
112 buf[2] = 0x80;
113 buf[3] = 0x80;
114 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
115 buf[1] = 0x80;
116 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
117}
118
Michal Vasko5aa44c02020-06-29 11:47:02 +0200119#ifndef __APPLE__
Radek Krejci36bac2b2018-09-19 11:15:29 +0200120void *__real_realloc(void *ptr, size_t size);
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100121void *
122__wrap_realloc(void *ptr, size_t size)
Radek Krejci36bac2b2018-09-19 11:15:29 +0200123{
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 Krejcib4ac5a92020-11-23 17:54:33 +0100157
Michal Vasko5aa44c02020-06-29 11:47:02 +0200158#endif /* not __APPLE__ */
Radek Krejci36bac2b2018-09-19 11:15:29 +0200159
Radek Krejcib4a4a272019-06-10 12:44:52 +0200160static void
Radek Krejci9ea8ca12019-06-10 13:11:55 +0200161test_parse_int(void **state)
162{
163 *state = test_parse_int;
164 const char *str;
165 int64_t i = 500;
166
167 str = "10";
168 assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
169 assert_int_equal(i, 10);
170
171 /* leading zeros are allowed, trailing whitespaces are allowed */
172 str = "000\n\t ";
173 assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
174 assert_int_equal(i, 0);
175
176 /* negative value */
177 str = "-10";
178 assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
179 assert_int_equal(i, -10);
180
181 /* non-NULL terminated string */
182 str = "+5sometext";
183 assert_int_equal(LY_SUCCESS, ly_parse_int(str, 2, -10, 10, 10, &i));
184 assert_int_equal(i, 5);
185
186 /* out of bounds value */
187 str = "11";
188 assert_int_equal(LY_EDENIED, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
189 str = "-11";
190 assert_int_equal(LY_EDENIED, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
191
192 /* NaN */
193 str = "zero";
194 assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
195
196 /* mixing number with text */
197 str = "10zero";
198 assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
199
200 str = "10 zero";
201 assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
202
203 *state = NULL;
204}
205
206static void
207test_parse_uint(void **state)
208{
209 *state = test_parse_int;
210 const char *str;
211 uint64_t u = 500;
212
213 str = "10";
214 assert_int_equal(LY_SUCCESS, ly_parse_uint(str, strlen(str), 10, 10, &u));
215 assert_int_equal(u, 10);
216
217 /* leading zeros are allowed, trailing whitespaces are allowed */
218 str = "000\n\t ";
219 assert_int_equal(LY_SUCCESS, ly_parse_uint(str, strlen(str), 10, 10, &u));
220 assert_int_equal(u, 0);
221 /* non-NULL terminated string */
222 str = "+5sometext";
223 assert_int_equal(LY_SUCCESS, ly_parse_uint(str, 2, 10, 10, &u));
224 assert_int_equal(u, 5);
225
226 /* out of bounds value */
227 str = "11";
228 assert_int_equal(LY_EDENIED, ly_parse_uint(str, strlen(str), 10, 10, &u));
229 str = "-1";
230 assert_int_equal(LY_EDENIED, ly_parse_uint(str, strlen(str), (uint64_t)-1, 10, &u));
231
232 /* NaN */
233 str = "zero";
234 assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
235
236 /* mixing number with text */
237 str = "10zero";
238 assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
239
240 str = "10 zero";
241 assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
242
243 *state = NULL;
244}
245
246static void
Radek Krejcib4a4a272019-06-10 12:44:52 +0200247test_parse_nodeid(void **state)
248{
Radek Krejci10bfdf82019-06-10 14:08:13 +0200249 *state = test_parse_nodeid;
Radek Krejcib4a4a272019-06-10 12:44:52 +0200250 const char *str;
251 const char *prefix, *name;
252 size_t prefix_len, name_len;
253
254 str = "123";
255 assert_int_equal(LY_EINVAL, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
256
257 str = "a12_-.!";
258 assert_int_equal(LY_SUCCESS, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
259 assert_null(prefix);
260 assert_int_equal(0, prefix_len);
261 assert_non_null(name);
262 assert_int_equal(6, name_len);
263 assert_int_equal(0, strncmp("a12_-.", name, name_len));
264 assert_string_equal("!", str);
265
266 str = "a12_-.:_b2 xxx";
267 assert_int_equal(LY_SUCCESS, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
268 assert_non_null(prefix);
269 assert_int_equal(6, prefix_len);
270 assert_int_equal(0, strncmp("a12_-.", prefix, prefix_len));
271 assert_non_null(name);
272 assert_int_equal(3, name_len);
273 assert_int_equal(0, strncmp("_b2", name, name_len));
274 assert_string_equal(" xxx", str);
Radek Krejci10bfdf82019-06-10 14:08:13 +0200275
276 *state = NULL;
277}
278
279static void
280test_parse_instance_predicate(void **state)
281{
282 *state = test_parse_instance_predicate;
283 const char *str, *errmsg;
284 const char *prefix, *id, *value;
285 size_t prefix_len, id_len, value_len;
286
287 str = "[ex:name='fred']";
Radek Krejci084289f2019-07-09 17:35:30 +0200288 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 +0200289 assert_string_equal(str, "");
290 assert_string_equal(prefix, "ex:name='fred']");
291 assert_int_equal(prefix_len, 2);
292 assert_string_equal(id, "name='fred']");
293 assert_int_equal(id_len, 4);
294 assert_string_equal(value, "fred']");
295 assert_int_equal(value_len, 4);
296
297 str = "[ex:ip = \"[192.0.2.1]\"][ex:port='80']";
Radek Krejci084289f2019-07-09 17:35:30 +0200298 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 +0200299 assert_string_equal(str, "[ex:port='80']");
300 assert_string_equal(prefix, "ex:ip = \"[192.0.2.1]\"][ex:port='80']");
301 assert_int_equal(prefix_len, 2);
302 assert_string_equal(id, "ip = \"[192.0.2.1]\"][ex:port='80']");
303 assert_int_equal(id_len, 2);
304 assert_string_equal(value, "[192.0.2.1]\"][ex:port='80']");
305 assert_int_equal(value_len, 11);
306
307 str = "[. = 'blowfish-cbc']";
Radek Krejci084289f2019-07-09 17:35:30 +0200308 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 +0200309 assert_string_equal(str, "");
310 assert_null(prefix);
311 assert_int_equal(prefix_len, 0);
312 assert_string_equal(id, ". = 'blowfish-cbc']");
313 assert_int_equal(id_len, 1);
314 assert_string_equal(value, "blowfish-cbc']");
315 assert_int_equal(value_len, 12);
316
317 str = "[ 3 ]";
Radek Krejci084289f2019-07-09 17:35:30 +0200318 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 +0200319 assert_string_equal(str, "");
320 assert_null(prefix);
321 assert_int_equal(prefix_len, 0);
322 assert_null(id);
323 assert_int_equal(id_len, 0);
324 assert_string_equal(value, "3 ]");
325 assert_int_equal(value_len, 1);
326
327 /* invalid predicates */
328 /* position must be positive integer */
329 str = "[0]";
Radek Krejci084289f2019-07-09 17:35:30 +0200330 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 +0200331 assert_string_equal(errmsg, "The position predicate cannot be zero.");
332 str = "[-1]";
Radek Krejci084289f2019-07-09 17:35:30 +0200333 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 +0200334 assert_string_equal(errmsg, "Invalid instance predicate format (negative position or invalid node-identifier).");
335
336 /* invalid node-identifier */
337 str = "[$node='value']";
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 node-identifier.");
340 str = "[.node='value']";
Radek Krejci084289f2019-07-09 17:35:30 +0200341 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 +0200342 assert_string_equal(errmsg, "Unexpected character instead of '=' in leaf-list-predicate.");
343 str = "[13node='value']";
Radek Krejci084289f2019-07-09 17:35:30 +0200344 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 +0200345 assert_string_equal(errmsg, "Predicate (pos) is not terminated by \']\' character.");
346
Radek Krejci084289f2019-07-09 17:35:30 +0200347 str = "[ex:node]";
348 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 +0200349 assert_string_equal(errmsg, "Unexpected character instead of '=' in key-predicate.");
350
Radek Krejci084289f2019-07-09 17:35:30 +0200351 str = "[ex:node= value]";
352 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 +0200353 assert_string_equal(errmsg, "String value is not quoted.");
354
Radek Krejci084289f2019-07-09 17:35:30 +0200355 str = "[ex:node='value\"]";
356 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 +0200357 assert_string_equal(errmsg, "Value is not terminated quoted-string.");
358
Radek Krejci084289f2019-07-09 17:35:30 +0200359 str = "[ex:node='value ]";
360 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 +0200361 assert_string_equal(errmsg, "Value is not terminated quoted-string.");
362
Radek Krejci084289f2019-07-09 17:35:30 +0200363 str = "[ex:node=\"value\"[3]";
364 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 +0200365 assert_string_equal(errmsg, "Predicate (key-predicate) is not terminated by \']\' character.");
366 str = "[.=\"value\"[3]";
Radek Krejci084289f2019-07-09 17:35:30 +0200367 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 +0200368 assert_string_equal(errmsg, "Predicate (leaf-list-predicate) is not terminated by \']\' character.");
369
Radek Krejci084289f2019-07-09 17:35:30 +0200370 /* the limit of the string is too short, it ends one character earlier */
371 str = "[ex:node='value']";
372 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 +0200373 assert_string_equal(errmsg, "Predicate is incomplete.");
374
375 *state = NULL;
Radek Krejcib4a4a272019-06-10 12:44:52 +0200376}
377
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100378int
379main(void)
Radek Krejci36bac2b2018-09-19 11:15:29 +0200380{
381 const struct CMUnitTest tests[] = {
Radek Krejcib4a4a272019-06-10 12:44:52 +0200382 cmocka_unit_test_setup_teardown(test_utf8, logger_setup, logger_teardown),
Michal Vasko5aa44c02020-06-29 11:47:02 +0200383#ifndef __APPLE__
Radek Krejci36bac2b2018-09-19 11:15:29 +0200384 cmocka_unit_test(test_lyrealloc),
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100385#endif
Radek Krejci9ea8ca12019-06-10 13:11:55 +0200386 cmocka_unit_test_setup_teardown(test_parse_int, logger_setup, logger_teardown),
387 cmocka_unit_test_setup_teardown(test_parse_uint, logger_setup, logger_teardown),
Radek Krejcib4a4a272019-06-10 12:44:52 +0200388 cmocka_unit_test_setup_teardown(test_parse_nodeid, logger_setup, logger_teardown),
Radek Krejci10bfdf82019-06-10 14:08:13 +0200389 cmocka_unit_test_setup_teardown(test_parse_instance_predicate, logger_setup, logger_teardown),
Radek Krejci36bac2b2018-09-19 11:15:29 +0200390 };
391
392 return cmocka_run_group_tests(tests, NULL, NULL);
393}