8 #include "../logctl/logctl.h"
10 static bool fail_calloc = false;
11 extern void *__real_calloc(size_t nmemb, size_t size);
12 void *__wrap_calloc(size_t nmemb, size_t size)
14 return fail_calloc ? NULL : __real_calloc(nmemb, size);
17 static bool fail_asprintf = false;
18 int __wrap_asprintf(char **strp, const char *fmt, ...)
25 const int ret = vasprintf(strp, fmt, va);
30 static bool fail_open;
31 int __real_open(const char *path, int flags, mode_t mode);
32 int __wrap_open(const char *path, int flags, mode_t mode)
34 return fail_open ? -1 : __real_open(path, flags, mode);
36 int __wrap_open64(const char *path, int flags, mode_t mode)
38 return __wrap_open(path, flags, mode);
41 static bool fail_fdopen;
42 FILE *__real_fdopen(int fd, const char *mode);
43 FILE *__wrap_fdopen(int fd, const char *mode)
45 return fail_fdopen ? NULL : __real_fdopen(fd, mode);
47 FILE *__wrap_fdopen64(int fd, const char *mode)
49 return __wrap_fdopen(fd, mode);
52 static bool fail_mkstemp;
53 int __real_mkstemp(char *template);
54 int __wrap_mkstemp(char *template)
56 return fail_mkstemp ? -1 : __real_mkstemp(template);
58 int __wrap_mkstemp64(char *template)
60 return __wrap_mkstemp(template);
63 static bool fail_fchmod;
64 int __real_fchmod(const char *path, mode_t mode);
65 int __wrap_fchmod(const char *path, mode_t mode)
67 return fail_fchmod ? -1 : __real_fchmod(path, mode);
70 static bool fail_rename;
71 int __real_rename(const char *oldpath, const char *newpath);
72 int __wrap_rename(const char *oldpath, const char *newpath)
74 return fail_rename ? -1 : __real_rename(oldpath, newpath);
77 static const char *const TMPFILE_PATH = "src/tests/logctl_testfile";
79 void _prepare_file(const char *const *lines, size_t lines_cnt)
81 __attribute__((cleanup(close_FILE))) FILE *const file_prep = fopen(TMPFILE_PATH, "w");
84 for (size_t i = 0; i < lines_cnt; ++i) {
85 assert(fputs(lines[i], file_prep) >= 0);
86 assert(fputc('\n', file_prep) == '\n');
89 #define PREPARE_FILE(lines) _prepare_file(lines, NELEMS(lines))
91 void _compare_file(const char *const *lines, size_t lines_cnt)
93 __attribute__((cleanup(close_FILE))) FILE *const file_result = fopen(TMPFILE_PATH, "r");
97 size_t lines_read = 0;
98 while (fgets(line, sizeof line, file_result)) {
99 assert(lines_read < lines_cnt);
101 const size_t expected_len = strlen(lines[lines_read]);
102 assert(line[expected_len] == '\n');
103 assert(!strncmp(line, lines[lines_read], expected_len));
108 #define COMPARE_FILE(lines) _compare_file(lines, NELEMS(lines))
110 void test_copy_file_with_exceptions()
112 static const char *const lines_in[] = {
119 static const char *const lines_out[] = {
124 static const struct kv {
133 PREPARE_FILE(lines_in);
135 struct keys_values kv = {
136 .keys = calloc(NELEMS(kv_pairs), sizeof *kv.keys),
137 .values = calloc(NELEMS(kv_pairs), sizeof *kv.values),
138 .n = NELEMS(kv_pairs),
142 for (size_t i = 0; i < kv.n; ++i) {
143 kv.keys[i] = kv_pairs[i].key;
144 kv.values[i] = kv_pairs[i].value;
147 assert(EXIT_SUCCESS == copy_file_with_exceptions(TMPFILE_PATH, &kv));
148 COMPARE_FILE(lines_out);
150 #define TEST_FAIL(callname) \
151 fail_##callname = true; \
152 assert(EXIT_FAILURE == copy_file_with_exceptions(TMPFILE_PATH, &kv)); \
153 fail_##callname = false;
155 assert(EXIT_SUCCESS == copy_file_with_exceptions(TMPFILE_PATH, &kv));
163 assert(EXIT_SUCCESS == copy_file_with_exceptions(TMPFILE_PATH, &kv));
171 void test_handle_clear()
173 static const char *const lines_in[] = {
183 static const char *const lines_out[] = {
190 PREPARE_FILE(lines_in);
191 assert(EXIT_SUCCESS == handle_clear(NULL, TMPFILE_PATH, NULL));
192 COMPARE_FILE(lines_out);
195 void test_handle_set()
197 static const char *const lines_in[] = {
204 static const char *const lines_set[] = {
211 static const char *const lines_clear[] = {
218 struct parsed_params pp;
219 PREPARE_FILE(lines_in);
224 assert(EXIT_SUCCESS == handle_set(&pp, TMPFILE_PATH, NULL));
225 COMPARE_FILE(lines_set);
230 assert(EXIT_SUCCESS == handle_set(&pp, TMPFILE_PATH, NULL));
231 COMPARE_FILE(lines_clear);
233 assert(EXIT_SUCCESS == handle_set(&pp, TMPFILE_PATH, NULL));
234 fail_asprintf = true;
235 assert(EXIT_FAILURE == handle_set(&pp, TMPFILE_PATH, NULL));
236 fail_asprintf = false;
237 assert(EXIT_SUCCESS == handle_set(&pp, TMPFILE_PATH, NULL));
240 void test_handle_plog()
242 static const char *const lines_in[] = {
249 static const char *const lines_enabled[] = {
257 static const char *const lines_disabled[] = {
265 static const char *const lines_all[] = {
277 struct parsed_params pp;
278 PREPARE_FILE(lines_in);
280 pp.plog_enable = true;
281 pp.plog_buffers_bitset = (1 << LOG_ID_MAIN) | (1 << LOG_ID_SYSTEM);
282 assert(EXIT_SUCCESS == handle_plog(&pp, TMPFILE_PATH, NULL));
283 COMPARE_FILE(lines_enabled);
285 pp.plog_enable = false;
286 pp.plog_buffers_bitset = (1 << LOG_ID_MAIN) | (1 << LOG_ID_RADIO);
287 assert(EXIT_SUCCESS == handle_plog(&pp, TMPFILE_PATH, NULL));
288 COMPARE_FILE(lines_disabled);
290 pp.plog_enable = true;
291 pp.plog_buffers_bitset = 0;
292 assert(EXIT_SUCCESS == handle_plog(&pp, TMPFILE_PATH, NULL));
293 COMPARE_FILE(lines_all);
296 assert(EXIT_FAILURE == handle_plog(&pp, TMPFILE_PATH, NULL));
299 fail_asprintf = true;
300 assert(EXIT_FAILURE == handle_plog(&pp, TMPFILE_PATH, NULL));
301 fail_asprintf = false;
303 assert(EXIT_SUCCESS == handle_plog(&pp, TMPFILE_PATH, NULL));
306 struct expected_opts {
309 struct parsed_params pp;
312 void check_option_set(size_t argc, const char **argv, const struct expected_opts *exp)
314 struct parsed_params pp = {0};
316 bool retval = parse_options((int) argc, argv, &pp, &exit_code);
322 assert(retval == exp->retval);
323 assert(retval || (exit_code == exp->exit_code));
324 assert(pp.action == exp->pp.action);
325 assert(pp.prio == exp->pp.prio);
326 assert(pp.plog_buffers_bitset == exp->pp.plog_buffers_bitset);
327 assert(pp.plog_enable == exp->pp.plog_enable);
328 assert(pp.value || !exp->pp.value);
329 assert(!pp.value || exp->pp.value);
330 assert(!pp.value || !strcmp(exp->pp.value, pp.value));
331 assert(pp.tag || !exp->pp.tag);
332 assert(!pp.tag || exp->pp.tag);
333 assert(!pp.tag || !strcmp(exp->pp.tag, pp.tag));
336 void test_parse_options()
338 /* These are primarily covered by integration tests but there's some value
339 * in running this at build time as well to detect any breakage ASAP. */
341 const char *none_args[] = { "x" , NULL};
342 const char *garbage_args[] = { "x", "--cactus" , NULL};
343 const char *clear_args[] = { "x", "-c", "-t", "tag_to_clear" , NULL};
344 const char *clr_all_args[] = { "x", "-c" , NULL};
345 const char *set_args[] = { "x", "-s", "15", "--priority", "e" , NULL};
346 const char *get_args[] = { "x", "-g", "-p", "*", "-t", "*" , NULL};
347 const char *dump_args[] = { "x", "-g" , NULL};
348 const char *enable_args[] = { "x", "--enable", "-b", "main", "-b", "radio", NULL};
349 const char *disable_args[] = { "x", "--disable", "-b", "main", "-b", "radio", NULL};
350 const char *help_args[] = { "x", "--help" , NULL};
352 const char *prio_err_args[] = { "x", "--priority", "]" , NULL};
353 const char *buf_err_args[] = { "x", "--buffer", "invalid" , NULL};
354 const char *plog_err_args[] = { "x", "-g", "--buffer", "main" , NULL};
355 const char *set_err_args[] = { "x", "-s", "tizen" , NULL};
357 static const struct expected_opts none_opts = { EXIT_SUCCESS, false, { ACTION_NONE , "*" , '\0', -1, NULL, false, 0 } };
358 static const struct expected_opts garbage_opts = { EXIT_SUCCESS, false, { ACTION_NONE , "*" , '\0', -1, NULL, false, 0 } };
359 static const struct expected_opts clear_opts = { EXIT_SUCCESS, true , { ACTION_SET , "tag_to_clear", '*', -1, NULL, false, 0 } };
360 static const struct expected_opts clr_all_opts = { EXIT_SUCCESS, true , { ACTION_CLEAR, "*" , '\0', -1, NULL, false, 0 } };
361 static const struct expected_opts set_opts = { EXIT_SUCCESS, true , { ACTION_SET , "*" , 'E', -1, "15", false, 0 } };
362 static const struct expected_opts get_opts = { EXIT_SUCCESS, true , { ACTION_GET , "*" , '*', -1, NULL, false, 0 } };
363 static const struct expected_opts dump_opts = { EXIT_SUCCESS, true , { ACTION_DUMP , "*" , '\0', -1, NULL, false, 0 } };
364 static const struct expected_opts enable_opts = { EXIT_SUCCESS, true , { ACTION_PLOG , "*" , '\0', -1, NULL, true , 1 << LOG_ID_MAIN | 1 << LOG_ID_RADIO } };
365 static const struct expected_opts disable_opts = { EXIT_SUCCESS, true , { ACTION_PLOG , "*" , '\0', -1, NULL, false, 1 << LOG_ID_MAIN | 1 << LOG_ID_RADIO } };
366 static const struct expected_opts help_opts = { EXIT_SUCCESS, false, { ACTION_NONE , "*" , '\0', -1, NULL, false, 0 } };
368 static const struct expected_opts prio_err_opts = { EXIT_FAILURE, false, { ACTION_NONE , "*" , ']', -1, NULL, false, 0 } };
369 static const struct expected_opts buf_err_opts = { EXIT_FAILURE, false, { ACTION_NONE , "*" , '\0', -1, NULL, false, 0 } };
370 static const struct expected_opts plog_err_opts = { EXIT_FAILURE, false, { ACTION_GET , "*" , '\0', -1, NULL, false, 1 << LOG_ID_MAIN } };
371 static const struct expected_opts set_err_opts = { EXIT_FAILURE, false, { ACTION_NONE , "*" , '\0', -1, NULL, false, 0 } };
373 #define CHECK_OPTION_SET(TYPE) check_option_set(NELEMS(TYPE##_args) - 1, TYPE##_args, &(TYPE##_opts))
374 CHECK_OPTION_SET(none);
375 CHECK_OPTION_SET(garbage);
376 CHECK_OPTION_SET(clear);
377 CHECK_OPTION_SET(clr_all);
378 CHECK_OPTION_SET(set);
379 CHECK_OPTION_SET(get);
380 CHECK_OPTION_SET(dump);
381 CHECK_OPTION_SET(enable);
382 CHECK_OPTION_SET(disable);
383 CHECK_OPTION_SET(help);
385 CHECK_OPTION_SET(prio_err);
386 CHECK_OPTION_SET(buf_err);
387 CHECK_OPTION_SET(plog_err);
388 CHECK_OPTION_SET(set_err);
389 #undef CHECK_OPTION_SET
394 test_copy_file_with_exceptions();
395 test_parse_options();