blob: d6e9ca3e61fe361b7f63999b7afabacb97a66b3c [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 Krejcica376bd2020-06-11 16:04:06 +020020#include <string.h>
21#include <stdlib.h>
22#include <stdio.h>
23
Radek Krejci70593c12020-06-13 20:48:09 +020024#include "common.h"
Radek Krejci36bac2b2018-09-19 11:15:29 +020025
26#define BUFSIZE 1024
27char logbuf[BUFSIZE] = {0};
Radek Krejcib4a4a272019-06-10 12:44:52 +020028int store = -1; /* negative for infinite logging, positive for limited logging */
Radek Krejci36bac2b2018-09-19 11:15:29 +020029
Radek Krejcib4a4a272019-06-10 12:44:52 +020030/* set to 0 to printing error messages to stderr instead of checking them in code */
31#define ENABLE_LOGGER_CHECKING 1
32
33#if ENABLE_LOGGER_CHECKING
Radek Krejci36bac2b2018-09-19 11:15:29 +020034static void
35logger(LY_LOG_LEVEL level, const char *msg, const char *path)
36{
37 (void) level; /* unused */
Radek Krejcib4a4a272019-06-10 12:44:52 +020038 if (store) {
39 if (path && path[0]) {
40 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
41 } else {
42 strncpy(logbuf, msg, BUFSIZE - 1);
43 }
44 if (store > 0) {
45 --store;
46 }
47 }
Radek Krejci36bac2b2018-09-19 11:15:29 +020048}
Radek Krejcib4a4a272019-06-10 12:44:52 +020049#endif
Radek Krejci36bac2b2018-09-19 11:15:29 +020050
51static int
52logger_setup(void **state)
53{
54 (void) state; /* unused */
55
56 ly_set_log_clb(logger, 0);
57
58 return 0;
59}
60
Radek Krejcib4a4a272019-06-10 12:44:52 +020061static int
62logger_teardown(void **state)
63{
64 (void) state; /* unused */
65#if ENABLE_LOGGER_CHECKING
66 if (*state) {
67 fprintf(stderr, "%s\n", logbuf);
68 }
69#endif
70 return 0;
71}
72
73void
74logbuf_clean(void)
75{
76 logbuf[0] = '\0';
77}
78
79#if ENABLE_LOGGER_CHECKING
80# define logbuf_assert(str) assert_string_equal(logbuf, str)
81#else
82# define logbuf_assert(str)
83#endif
84
Radek Krejci36bac2b2018-09-19 11:15:29 +020085static void
Radek Krejci44ceedc2018-10-02 15:54:31 +020086test_utf8(void **state)
87{
88 (void) state; /* unused */
89
90 char buf[5] = {0};
91 const char *str = buf;
92 unsigned int c;
93 size_t len;
94
95 /* test invalid UTF-8 characters in lyxml_getutf8
96 * - https://en.wikipedia.org/wiki/UTF-8 */
97 buf[0] = 0x04;
98 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
99 buf[0] = 0x80;
100 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
101
102 buf[0] = 0xc0;
103 buf[1] = 0x00;
104 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
105 buf[1] = 0x80;
106 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
107
108 buf[0] = 0xe0;
109 buf[1] = 0x00;
110 buf[2] = 0x80;
111 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
112 buf[1] = 0x80;
113 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
114
115 buf[0] = 0xf0;
116 buf[1] = 0x00;
117 buf[2] = 0x80;
118 buf[3] = 0x80;
119 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
120 buf[1] = 0x80;
121 assert_int_equal(LY_EINVAL, ly_getutf8(&str, &c, &len));
122}
123
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100124#ifndef APPLE
Radek Krejci36bac2b2018-09-19 11:15:29 +0200125void *__real_realloc(void *ptr, size_t size);
126void *__wrap_realloc(void *ptr, size_t size)
127{
128 int wrap = mock_type(int);
129
130 if (wrap) {
131 /* memory allocation failed */
132 return NULL;
133 } else {
134 return __real_realloc(ptr, size);
135 }
136}
137
138static void
139test_lyrealloc(void **state)
140{
141 (void) state; /* unused */
142
143 char *ptr;
144
145 ptr = malloc(1);
146 assert_non_null(ptr);
147
148 /* realloc */
149 will_return(__wrap_realloc, 0);
150 ptr = ly_realloc(ptr, 2048);
151 assert_non_null(ptr);
152 ptr[2047] = 0; /* test write */
153
154 /* realloc fails */
155 will_return(__wrap_realloc, 1);
156 ptr = ly_realloc(ptr, 2048);
157 assert_null(ptr);
158
159 /* ptr should be freed by ly_realloc() */
160}
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100161#endif /* not APPLE */
Radek Krejci36bac2b2018-09-19 11:15:29 +0200162
Radek Krejcib4a4a272019-06-10 12:44:52 +0200163static void
Radek Krejci9ea8ca12019-06-10 13:11:55 +0200164test_parse_int(void **state)
165{
166 *state = test_parse_int;
167 const char *str;
168 int64_t i = 500;
169
170 str = "10";
171 assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
172 assert_int_equal(i, 10);
173
174 /* leading zeros are allowed, trailing whitespaces are allowed */
175 str = "000\n\t ";
176 assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
177 assert_int_equal(i, 0);
178
179 /* negative value */
180 str = "-10";
181 assert_int_equal(LY_SUCCESS, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
182 assert_int_equal(i, -10);
183
184 /* non-NULL terminated string */
185 str = "+5sometext";
186 assert_int_equal(LY_SUCCESS, ly_parse_int(str, 2, -10, 10, 10, &i));
187 assert_int_equal(i, 5);
188
189 /* out of bounds value */
190 str = "11";
191 assert_int_equal(LY_EDENIED, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
192 str = "-11";
193 assert_int_equal(LY_EDENIED, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
194
195 /* NaN */
196 str = "zero";
197 assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
198
199 /* mixing number with text */
200 str = "10zero";
201 assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
202
203 str = "10 zero";
204 assert_int_equal(LY_EVALID, ly_parse_int(str, strlen(str), -10, 10, 10, &i));
205
206 *state = NULL;
207}
208
209static void
210test_parse_uint(void **state)
211{
212 *state = test_parse_int;
213 const char *str;
214 uint64_t u = 500;
215
216 str = "10";
217 assert_int_equal(LY_SUCCESS, ly_parse_uint(str, strlen(str), 10, 10, &u));
218 assert_int_equal(u, 10);
219
220 /* leading zeros are allowed, trailing whitespaces are allowed */
221 str = "000\n\t ";
222 assert_int_equal(LY_SUCCESS, ly_parse_uint(str, strlen(str), 10, 10, &u));
223 assert_int_equal(u, 0);
224 /* non-NULL terminated string */
225 str = "+5sometext";
226 assert_int_equal(LY_SUCCESS, ly_parse_uint(str, 2, 10, 10, &u));
227 assert_int_equal(u, 5);
228
229 /* out of bounds value */
230 str = "11";
231 assert_int_equal(LY_EDENIED, ly_parse_uint(str, strlen(str), 10, 10, &u));
232 str = "-1";
233 assert_int_equal(LY_EDENIED, ly_parse_uint(str, strlen(str), (uint64_t)-1, 10, &u));
234
235 /* NaN */
236 str = "zero";
237 assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
238
239 /* mixing number with text */
240 str = "10zero";
241 assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
242
243 str = "10 zero";
244 assert_int_equal(LY_EVALID, ly_parse_uint(str, strlen(str), 10, 10, &u));
245
246 *state = NULL;
247}
248
249static void
Radek Krejcib4a4a272019-06-10 12:44:52 +0200250test_parse_nodeid(void **state)
251{
Radek Krejci10bfdf82019-06-10 14:08:13 +0200252 *state = test_parse_nodeid;
Radek Krejcib4a4a272019-06-10 12:44:52 +0200253 const char *str;
254 const char *prefix, *name;
255 size_t prefix_len, name_len;
256
257 str = "123";
258 assert_int_equal(LY_EINVAL, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
259
260 str = "a12_-.!";
261 assert_int_equal(LY_SUCCESS, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
262 assert_null(prefix);
263 assert_int_equal(0, prefix_len);
264 assert_non_null(name);
265 assert_int_equal(6, name_len);
266 assert_int_equal(0, strncmp("a12_-.", name, name_len));
267 assert_string_equal("!", str);
268
269 str = "a12_-.:_b2 xxx";
270 assert_int_equal(LY_SUCCESS, ly_parse_nodeid(&str, &prefix, &prefix_len, &name, &name_len));
271 assert_non_null(prefix);
272 assert_int_equal(6, prefix_len);
273 assert_int_equal(0, strncmp("a12_-.", prefix, prefix_len));
274 assert_non_null(name);
275 assert_int_equal(3, name_len);
276 assert_int_equal(0, strncmp("_b2", name, name_len));
277 assert_string_equal(" xxx", str);
Radek Krejci10bfdf82019-06-10 14:08:13 +0200278
279 *state = NULL;
280}
281
282static void
283test_parse_instance_predicate(void **state)
284{
285 *state = test_parse_instance_predicate;
286 const char *str, *errmsg;
287 const char *prefix, *id, *value;
288 size_t prefix_len, id_len, value_len;
289
290 str = "[ex:name='fred']";
Radek Krejci084289f2019-07-09 17:35:30 +0200291 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 +0200292 assert_string_equal(str, "");
293 assert_string_equal(prefix, "ex:name='fred']");
294 assert_int_equal(prefix_len, 2);
295 assert_string_equal(id, "name='fred']");
296 assert_int_equal(id_len, 4);
297 assert_string_equal(value, "fred']");
298 assert_int_equal(value_len, 4);
299
300 str = "[ex:ip = \"[192.0.2.1]\"][ex:port='80']";
Radek Krejci084289f2019-07-09 17:35:30 +0200301 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 +0200302 assert_string_equal(str, "[ex:port='80']");
303 assert_string_equal(prefix, "ex:ip = \"[192.0.2.1]\"][ex:port='80']");
304 assert_int_equal(prefix_len, 2);
305 assert_string_equal(id, "ip = \"[192.0.2.1]\"][ex:port='80']");
306 assert_int_equal(id_len, 2);
307 assert_string_equal(value, "[192.0.2.1]\"][ex:port='80']");
308 assert_int_equal(value_len, 11);
309
310 str = "[. = 'blowfish-cbc']";
Radek Krejci084289f2019-07-09 17:35:30 +0200311 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 +0200312 assert_string_equal(str, "");
313 assert_null(prefix);
314 assert_int_equal(prefix_len, 0);
315 assert_string_equal(id, ". = 'blowfish-cbc']");
316 assert_int_equal(id_len, 1);
317 assert_string_equal(value, "blowfish-cbc']");
318 assert_int_equal(value_len, 12);
319
320 str = "[ 3 ]";
Radek Krejci084289f2019-07-09 17:35:30 +0200321 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 +0200322 assert_string_equal(str, "");
323 assert_null(prefix);
324 assert_int_equal(prefix_len, 0);
325 assert_null(id);
326 assert_int_equal(id_len, 0);
327 assert_string_equal(value, "3 ]");
328 assert_int_equal(value_len, 1);
329
330 /* invalid predicates */
331 /* position must be positive integer */
332 str = "[0]";
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, "The position predicate cannot be zero.");
335 str = "[-1]";
Radek Krejci084289f2019-07-09 17:35:30 +0200336 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 +0200337 assert_string_equal(errmsg, "Invalid instance predicate format (negative position or invalid node-identifier).");
338
339 /* 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, "Invalid node-identifier.");
343 str = "[.node='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, "Unexpected character instead of '=' in leaf-list-predicate.");
346 str = "[13node='value']";
Radek Krejci084289f2019-07-09 17:35:30 +0200347 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, "Predicate (pos) is not terminated by \']\' character.");
349
Radek Krejci084289f2019-07-09 17:35:30 +0200350 str = "[ex:node]";
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, "Unexpected character instead of '=' in key-predicate.");
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, "String value is not quoted.");
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 ]";
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, "Value is not terminated quoted-string.");
365
Radek Krejci084289f2019-07-09 17:35:30 +0200366 str = "[ex:node=\"value\"[3]";
367 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 (key-predicate) is not terminated by \']\' character.");
369 str = "[.=\"value\"[3]";
Radek Krejci084289f2019-07-09 17:35:30 +0200370 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 +0200371 assert_string_equal(errmsg, "Predicate (leaf-list-predicate) is not terminated by \']\' character.");
372
Radek Krejci084289f2019-07-09 17:35:30 +0200373 /* the limit of the string is too short, it ends one character earlier */
374 str = "[ex:node='value']";
375 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 +0200376 assert_string_equal(errmsg, "Predicate is incomplete.");
377
378 *state = NULL;
Radek Krejcib4a4a272019-06-10 12:44:52 +0200379}
380
Radek Krejci36bac2b2018-09-19 11:15:29 +0200381int main(void)
382{
383 const struct CMUnitTest tests[] = {
Radek Krejcib4a4a272019-06-10 12:44:52 +0200384 cmocka_unit_test_setup_teardown(test_utf8, logger_setup, logger_teardown),
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100385#ifndef APPLE
Radek Krejci36bac2b2018-09-19 11:15:29 +0200386 cmocka_unit_test(test_lyrealloc),
Radek Krejci1b5ef9d2018-11-27 12:49:59 +0100387#endif
Radek Krejci9ea8ca12019-06-10 13:11:55 +0200388 cmocka_unit_test_setup_teardown(test_parse_int, logger_setup, logger_teardown),
389 cmocka_unit_test_setup_teardown(test_parse_uint, logger_setup, logger_teardown),
Radek Krejcib4a4a272019-06-10 12:44:52 +0200390 cmocka_unit_test_setup_teardown(test_parse_nodeid, logger_setup, logger_teardown),
Radek Krejci10bfdf82019-06-10 14:08:13 +0200391 cmocka_unit_test_setup_teardown(test_parse_instance_predicate, logger_setup, logger_teardown),
Radek Krejci36bac2b2018-09-19 11:15:29 +0200392 };
393
394 return cmocka_run_group_tests(tests, NULL, NULL);
395}