blob: 3fbda0896adf610a55d942c5af9d92bf1ffcc3ca [file] [log] [blame]
Michal Vasko00cbf532020-06-15 13:58:47 +02001/**
Radek Krejcif0e1ba52020-05-22 15:14:35 +02002 * @file test_inout.c
3 * @author: Radek Krejci <rkrejci@cesnet.cz>
4 * @brief unit tests for input and output handlers functions
5 *
Michal Vasko00cbf532020-06-15 13:58:47 +02006 * Copyright (c) 2020 CESNET, z.s.p.o.
Radek Krejcif0e1ba52020-05-22 15:14:35 +02007 *
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 Krejci70593c12020-06-13 20:48:09 +020015#define _POSIX_C_SOURCE 200112L
Radek Krejcif0e1ba52020-05-22 15:14:35 +020016
Radek Krejcif0e1ba52020-05-22 15:14:35 +020017#include <errno.h>
18#include <fcntl.h>
Radek Krejci70593c12020-06-13 20:48:09 +020019#include <stdio.h>
Radek Krejcif0e1ba52020-05-22 15:14:35 +020020#include <sys/stat.h>
Radek Krejcib4ac5a92020-11-23 17:54:33 +010021#include <sys/types.h>
Radek Krejcif0e1ba52020-05-22 15:14:35 +020022#include <unistd.h>
23
Radek Krejci70593c12020-06-13 20:48:09 +020024#include "common.h"
Radek Krejcib4ac5a92020-11-23 17:54:33 +010025#include "in.h"
Radek Krejci70593c12020-06-13 20:48:09 +020026#include "log.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020027#include "out.h"
Radek Krejcib4ac5a92020-11-23 17:54:33 +010028#include "utests.h"
Radek Krejcif0e1ba52020-05-22 15:14:35 +020029
30#define BUFSIZE 1024
31char logbuf[BUFSIZE] = {0};
32int store = -1; /* negative for infinite logging, positive for limited logging */
33
34/* set to 0 to printing error messages to stderr instead of checking them in code */
35#define ENABLE_LOGGER_CHECKING 1
36
37#if ENABLE_LOGGER_CHECKING
38static void
39logger(LY_LOG_LEVEL level, const char *msg, const char *path)
40{
41 (void) level; /* unused */
42 if (store) {
43 if (path && path[0]) {
44 snprintf(logbuf, BUFSIZE - 1, "%s %s", msg, path);
45 } else {
46 strncpy(logbuf, msg, BUFSIZE - 1);
47 }
48 if (store > 0) {
49 --store;
50 }
51 }
52}
Radek Krejcib4ac5a92020-11-23 17:54:33 +010053
Radek Krejcif0e1ba52020-05-22 15:14:35 +020054#endif
55
56static int
57logger_setup(void **state)
58{
59 (void) state; /* unused */
60
61 ly_set_log_clb(logger, 0);
62
63 return 0;
64}
65
66static int
67logger_teardown(void **state)
68{
69 (void) state; /* unused */
70#if ENABLE_LOGGER_CHECKING
71 if (*state) {
72 fprintf(stderr, "%s\n", logbuf);
73 }
74#endif
75 return 0;
76}
77
78void
79logbuf_clean(void)
80{
81 logbuf[0] = '\0';
82}
83
84#if ENABLE_LOGGER_CHECKING
85# define logbuf_assert(str) assert_string_equal(logbuf, str)
86#else
87# define logbuf_assert(str)
88#endif
89
90static void
91test_input_mem(void **state)
92{
93 struct ly_in *in = NULL;
94 char *str1 = "a", *str2 = "b";
95
96 *state = test_input_mem;
97
98 assert_int_equal(LY_EINVAL, ly_in_new_memory(NULL, NULL));
99 assert_int_equal(LY_EINVAL, ly_in_new_memory(str1, NULL));
100 assert_null(ly_in_memory(NULL, NULL));
101
102 assert_int_equal(LY_SUCCESS, ly_in_new_memory(str1, &in));
103 assert_int_equal(LY_IN_MEMORY, ly_in_type(in));
104 assert_ptr_equal(str1, ly_in_memory(in, str2));
105 assert_ptr_equal(str2, ly_in_memory(in, NULL));
106 assert_ptr_equal(str2, ly_in_memory(in, NULL));
107 ly_in_free(in, 0);
108
109 /* cleanup */
110 *state = NULL;
111}
112
113static void
114test_input_fd(void **state)
115{
116 struct ly_in *in = NULL;
117 int fd1, fd2;
118 struct stat statbuf;
119
120 *state = test_input_fd;
121
122 assert_int_equal(LY_EINVAL, ly_in_new_fd(-1, NULL));
123 assert_int_equal(-1, ly_in_fd(NULL, -1));
124
125 assert_int_not_equal(-1, fd1 = open(__FILE__, O_RDONLY));
126 assert_int_not_equal(-1, fd2 = open(__FILE__, O_RDONLY));
127
128 assert_int_equal(LY_EINVAL, ly_in_new_fd(fd1, NULL));
129
130 assert_int_equal(LY_SUCCESS, ly_in_new_fd(fd1, &in));
131 assert_int_equal(LY_IN_FD, ly_in_type(in));
132 assert_ptr_equal(fd1, ly_in_fd(in, fd2));
133 assert_ptr_equal(fd2, ly_in_fd(in, -1));
134 assert_ptr_equal(fd2, ly_in_fd(in, -1));
135 ly_in_free(in, 1);
136 /* fd1 is still open */
137 assert_int_equal(0, fstat(fd1, &statbuf));
138 close(fd1);
139 /* but fd2 was closed by ly_in_free() */
140 errno = 0;
141 assert_int_equal(-1, fstat(fd2, &statbuf));
142 assert_int_equal(errno, EBADF);
143
144 /* cleanup */
145 *state = NULL;
146}
147
148static void
149test_input_file(void **state)
150{
151 struct ly_in *in = NULL;
152 FILE *f1 = NULL, *f2 = NULL;
153
154 *state = test_input_file;
155
156 assert_int_equal(LY_EINVAL, ly_in_new_file(NULL, NULL));
157 assert_null(ly_in_file(NULL, NULL));
158
159 assert_int_not_equal(-1, f1 = fopen(__FILE__, "r"));
160 assert_int_not_equal(-1, f2 = fopen(__FILE__, "r"));
161
162 assert_int_equal(LY_EINVAL, ly_in_new_file(f1, NULL));
163
164 assert_int_equal(LY_SUCCESS, ly_in_new_file(f1, &in));
165 assert_int_equal(LY_IN_FILE, ly_in_type(in));
166 assert_ptr_equal(f1, ly_in_file(in, f2));
167 assert_ptr_equal(f2, ly_in_file(in, NULL));
168 assert_ptr_equal(f2, ly_in_file(in, NULL));
169 ly_in_free(in, 1);
170 /* f1 is still open */
171 assert_int_not_equal(-1, fileno(f1));
172 fclose(f1);
173 /* but f2 was closed by ly_in_free() */
174
175 /* cleanup */
176 *state = NULL;
177}
178
179static void
180test_input_filepath(void **state)
181{
182 struct ly_in *in = NULL;
183 const char *path1 = __FILE__, *path2 = __FILE__;
184
185 *state = test_input_filepath;
186
187 assert_int_equal(LY_EINVAL, ly_in_new_filepath(NULL, 0, NULL));
188 assert_int_equal(LY_EINVAL, ly_in_new_filepath(path1, 0, NULL));
189 assert_ptr_equal(((void *)-1), ly_in_filepath(NULL, NULL, 0));
190
191 assert_int_equal(LY_SUCCESS, ly_in_new_filepath(path1, 0, &in));
192 assert_int_equal(LY_IN_FILEPATH, ly_in_type(in));
193 assert_ptr_equal(NULL, ly_in_filepath(in, path2, 0));
194 assert_string_equal(path2, ly_in_filepath(in, NULL, 0));
195 ly_in_free(in, 0);
196
197 /* cleanup */
198 *state = NULL;
199}
200
201static void
202test_output_mem(void **state)
203{
204 struct ly_out *out = NULL;
205 char *buf1 = NULL, *buf2 = NULL;
206
207 *state = test_output_mem;
208
209 /* manipulate with the handler */
210 assert_int_equal(LY_SUCCESS, ly_out_new_memory(&buf1, 0, &out));
211 assert_int_equal(LY_OUT_MEMORY, ly_out_type(out));
212 ly_write(out, "test", 4);
213 assert_ptr_equal(buf1, ly_out_memory(out, &buf2, 0));
214 assert_ptr_equal(buf2, ly_out_memory(out, NULL, 0));
215 assert_ptr_equal(buf2, ly_out_memory(out, &buf1, strlen(buf1)));
216 ly_out_free(out, NULL, 0);
217
218 assert_int_equal(LY_SUCCESS, ly_out_new_memory(&buf1, strlen(buf1), &out));
219 ly_out_free(out, NULL, 1);
220
221 /* writing data */
222
223 assert_int_equal(LY_SUCCESS, ly_out_new_memory(&buf1, 0, &out));
Michal Vasko5233e962020-08-14 14:26:20 +0200224 assert_int_equal(LY_SUCCESS, ly_print(out, "test %s", "print"));
225 assert_int_equal(10, ly_out_printed(out));
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200226 assert_string_equal("test print", buf1);
227 assert_int_equal(LY_SUCCESS, ly_out_reset(out));
Michal Vasko5233e962020-08-14 14:26:20 +0200228 assert_int_equal(LY_SUCCESS, ly_write(out, "rewrite", 8));
229 assert_int_equal(8, ly_out_printed(out));
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200230 assert_string_equal("rewrite", buf1);
231 ly_out_free(out, NULL, 1);
232
233 /* cleanup */
234 *state = NULL;
235}
236
237static void
238test_output_fd(void **state)
239{
240 struct ly_out *out = NULL;
241 int fd1, fd2;
242 char buf[31] = {0};
243 const char *filepath = "/tmp/libyang_test_output";
244
245 *state = test_output_fd;
246
247 assert_int_not_equal(-1, fd1 = open(filepath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
248 assert_int_not_equal(-1, fd2 = open(filepath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
249
250 /* manipulate with the handler */
251 assert_int_equal(LY_SUCCESS, ly_out_new_fd(fd1, &out));
252 assert_int_equal(LY_OUT_FD, ly_out_type(out));
253 assert_ptr_equal(fd1, ly_out_fd(out, fd2));
254 assert_ptr_equal(fd2, ly_out_fd(out, -1));
255 assert_ptr_equal(fd2, ly_out_fd(out, fd1));
256 ly_out_free(out, NULL, 0);
257 assert_int_equal(0, close(fd2));
258 assert_int_equal(LY_SUCCESS, ly_out_new_fd(fd1, &out));
259 ly_out_free(out, NULL, 1);
260
261 /* writing data */
262 assert_int_not_equal(-1, fd1 = open(filepath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
263 assert_int_not_equal(-1, fd2 = open(filepath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
264 /* truncate file to start with no data */
265 assert_int_equal(0, ftruncate(fd1, 0));
266
267 assert_int_equal(LY_SUCCESS, ly_out_new_fd(fd1, &out));
Michal Vasko5233e962020-08-14 14:26:20 +0200268 assert_int_equal(LY_SUCCESS, ly_print(out, "test %s", "print"));
269 assert_int_equal(10, ly_out_printed(out));
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200270 ly_print_flush(out);
271 assert_int_equal(10, read(fd2, buf, 30));
272 assert_string_equal("test print", buf);
273 assert_int_equal(0, lseek(fd2, 0, SEEK_SET));
274 assert_int_equal(LY_SUCCESS, ly_out_reset(out));
275
Michal Vasko5233e962020-08-14 14:26:20 +0200276 assert_int_equal(LY_SUCCESS, ly_write(out, "rewrite", 8));
277 assert_int_equal(8, ly_out_printed(out));
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200278 ly_print_flush(out);
279 assert_int_equal(8, read(fd2, buf, 30));
280 assert_string_equal("rewrite", buf);
281
282 close(fd2);
283 ly_out_free(out, NULL, 1);
284
285 /* cleanup */
286 *state = NULL;
287}
288
289static void
290test_output_file(void **state)
291{
292 struct ly_out *out = NULL;
293 FILE *f1, *f2;
294 char buf[31] = {0};
295 const char *filepath = "/tmp/libyang_test_output";
296
297 *state = test_output_file;
298
299 assert_int_not_equal(-1, f1 = fopen(filepath, "w"));
300 assert_int_not_equal(-1, f2 = fopen(filepath, "w"));
301
302 /* manipulate with the handler */
303 assert_int_equal(LY_SUCCESS, ly_out_new_file(f1, &out));
304 assert_int_equal(LY_OUT_FILE, ly_out_type(out));
305 assert_ptr_equal(f1, ly_out_file(out, f2));
306 assert_ptr_equal(f2, ly_out_file(out, NULL));
307 assert_ptr_equal(f2, ly_out_file(out, f1));
308 ly_out_free(out, NULL, 0);
309 assert_int_equal(0, fclose(f2));
310 assert_int_equal(LY_SUCCESS, ly_out_new_file(f1, &out));
311 ly_out_free(out, NULL, 1);
312
313 /* writing data */
314 assert_int_not_equal(-1, f1 = fopen(filepath, "w"));
315 assert_int_not_equal(-1, f2 = fopen(filepath, "r"));
316
317 assert_int_equal(LY_SUCCESS, ly_out_new_file(f1, &out));
Michal Vasko5233e962020-08-14 14:26:20 +0200318 assert_int_equal(LY_SUCCESS, ly_print(out, "test %s", "print"));
319 assert_int_equal(10, ly_out_printed(out));
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200320 ly_print_flush(out);
321 assert_non_null(fgets(buf, 31, f2));
322 assert_string_equal("test print", buf);
323 assert_int_equal(0, fseek(f2, 0, SEEK_SET));
324 assert_int_equal(LY_SUCCESS, ly_out_reset(out));
325
Michal Vasko5233e962020-08-14 14:26:20 +0200326 assert_int_equal(LY_SUCCESS, ly_write(out, "rewrite", 8));
327 assert_int_equal(8, ly_out_printed(out));
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200328 ly_print_flush(out);
329 assert_non_null(fgets(buf, 31, f2));
330 assert_string_equal("rewrite", buf);
331
332 fclose(f2);
333 ly_out_free(out, NULL, 1);
334
335 /* cleanup */
336 *state = NULL;
337}
338
339static void
340test_output_filepath(void **state)
341{
342 struct ly_out *out = NULL;
343 FILE *f1;
344 char buf[31] = {0};
345 const char *fp1 = "/tmp/libyang_test_output";
346 const char *fp2 = "/tmp/libyang_test_output2";
347
348 *state = test_output_filepath;
349
350 /* manipulate with the handler */
351 assert_int_equal(LY_SUCCESS, ly_out_new_filepath(fp1, &out));
352 assert_int_equal(LY_OUT_FILEPATH, ly_out_type(out));
353 assert_ptr_equal(NULL, ly_out_filepath(out, fp2));
354 assert_string_equal(fp2, ly_out_filepath(out, NULL));
355 assert_ptr_equal(NULL, ly_out_filepath(out, fp1));
356 ly_out_free(out, NULL, 0);
357 assert_int_equal(LY_SUCCESS, ly_out_new_filepath(fp1, &out));
358 ly_out_free(out, NULL, 1);
359
360 /* writing data */
361 assert_int_not_equal(-1, f1 = fopen(fp1, "r"));
362
363 assert_int_equal(LY_SUCCESS, ly_out_new_filepath(fp1, &out));
Michal Vasko5233e962020-08-14 14:26:20 +0200364 assert_int_equal(LY_SUCCESS, ly_print(out, "test %s", "print"));
365 assert_int_equal(10, ly_out_printed(out));
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200366 ly_print_flush(out);
367 assert_non_null(fgets(buf, 31, f1));
368 assert_string_equal("test print", buf);
369 assert_int_equal(0, fseek(f1, 0, SEEK_SET));
370 assert_int_equal(LY_SUCCESS, ly_out_reset(out));
371
Michal Vasko5233e962020-08-14 14:26:20 +0200372 assert_int_equal(LY_SUCCESS, ly_write(out, "rewrite", 8));
373 assert_int_equal(8, ly_out_printed(out));
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200374 ly_print_flush(out);
375 assert_non_null(fgets(buf, 31, f1));
376 assert_string_equal("rewrite", buf);
377
378 fclose(f1);
379 ly_out_free(out, NULL, 1);
380
381 /* cleanup */
382 *state = NULL;
383}
384
385static void
386test_output_clb(void **state)
387{
388 struct ly_out *out = NULL;
389 int fd1, fd2;
390 char buf[31] = {0};
391 const char *filepath = "/tmp/libyang_test_output";
392
393 *state = test_output_clb;
394
395 assert_int_not_equal(-1, fd1 = open(filepath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
396 assert_int_not_equal(-1, fd2 = open(filepath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
397
398 /* manipulate with the handler */
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100399 assert_int_equal(LY_SUCCESS, ly_out_new_clb((void *)write, (void *)(intptr_t)fd1, &out));
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200400 assert_int_equal(LY_OUT_CALLBACK, ly_out_type(out));
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100401 assert_ptr_equal(fd1, ly_out_clb_arg(out, (void *)(intptr_t)fd2));
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200402 assert_ptr_equal(fd2, ly_out_clb_arg(out, NULL));
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100403 assert_ptr_equal(fd2, ly_out_clb_arg(out, (void *)(intptr_t)fd1));
Michal Vaskoed213e12020-10-15 11:12:35 +0200404 assert_ptr_equal(write, ly_out_clb(out, (void *)write));
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200405 ly_out_free(out, NULL, 0);
406 assert_int_equal(0, close(fd2));
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100407 assert_int_equal(LY_SUCCESS, ly_out_new_clb((void *)write, (void *)(intptr_t)fd1, &out));
Michal Vaskoed213e12020-10-15 11:12:35 +0200408 ly_out_free(out, (void *)close, 0);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200409
410 /* writing data */
411 assert_int_not_equal(-1, fd1 = open(filepath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
412 assert_int_not_equal(-1, fd2 = open(filepath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
413 /* truncate file to start with no data */
414 assert_int_equal(0, ftruncate(fd1, 0));
415
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100416 assert_int_equal(LY_SUCCESS, ly_out_new_clb((void *)write, (void *)(intptr_t)fd1, &out));
Michal Vasko5233e962020-08-14 14:26:20 +0200417 assert_int_equal(LY_SUCCESS, ly_print(out, "test %s", "print"));
418 assert_int_equal(10, ly_out_printed(out));
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200419 assert_int_equal(10, read(fd2, buf, 30));
420 assert_string_equal("test print", buf);
421
422 close(fd2);
Michal Vaskoed213e12020-10-15 11:12:35 +0200423 ly_out_free(out, (void *)close, 0);
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200424
425 /* cleanup */
426 *state = NULL;
427}
428
Radek Krejcib4ac5a92020-11-23 17:54:33 +0100429int
430main(void)
Radek Krejcif0e1ba52020-05-22 15:14:35 +0200431{
432 const struct CMUnitTest tests[] = {
433 cmocka_unit_test_setup_teardown(test_input_mem, logger_setup, logger_teardown),
434 cmocka_unit_test_setup_teardown(test_input_fd, logger_setup, logger_teardown),
435 cmocka_unit_test_setup_teardown(test_input_file, logger_setup, logger_teardown),
436 cmocka_unit_test_setup_teardown(test_input_filepath, logger_setup, logger_teardown),
437 cmocka_unit_test_setup_teardown(test_output_mem, logger_setup, logger_teardown),
438 cmocka_unit_test_setup_teardown(test_output_fd, logger_setup, logger_teardown),
439 cmocka_unit_test_setup_teardown(test_output_file, logger_setup, logger_teardown),
440 cmocka_unit_test_setup_teardown(test_output_filepath, logger_setup, logger_teardown),
441 cmocka_unit_test_setup_teardown(test_output_clb, logger_setup, logger_teardown),
442 };
443
444 return cmocka_run_group_tests(tests, NULL, NULL);
445}