From: Michal Bloch Date: Thu, 24 Jan 2019 18:30:40 +0000 (+0100) Subject: tests: further expand logctl unit tests X-Git-Tag: accepted/tizen/unified/20190201.061322~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=00a4f9061a6f0ca95afe1e199dbcbd94f436fd6c;p=platform%2Fcore%2Fsystem%2Fdlog.git tests: further expand logctl unit tests Change-Id: I022b9e8c090a2bcfcff7b7e7d697257f73d545cc Signed-off-by: Michal Bloch --- diff --git a/include/logctl.h b/include/logctl.h index 068c9af..31154a1 100644 --- a/include/logctl.h +++ b/include/logctl.h @@ -19,8 +19,8 @@ struct parsed_params { const char *tag; char prio; const char *value; - int plog_buffers_bitset; bool plog_enable; + int plog_buffers_bitset; }; struct keys_values { @@ -33,3 +33,7 @@ bool parse_options(int argc, const char **argv, struct parsed_params *params, in int copy_file_with_exceptions(const char *config_path, struct keys_values *kv); +int handle_set(const struct parsed_params *params, const char *config_path, struct log_config *conf); +int handle_plog(const struct parsed_params *params, const char *config_path, struct log_config *conf); +int handle_clear(const struct parsed_params *params, const char *config_path, struct log_config *conf); + diff --git a/src/logctl/logctl.c b/src/logctl/logctl.c index f809b0c..3cb6835 100644 --- a/src/logctl/logctl.c +++ b/src/logctl/logctl.c @@ -298,7 +298,7 @@ remove_temp: return EXIT_FAILURE; } -int handle_set(const struct parsed_params *params, char *config_path, struct log_config *conf) +int handle_set(const struct parsed_params *params, const char *config_path, struct log_config *conf) { __attribute__((cleanup(free_ptr))) char *key; if (asprintf(&key, "limiter|%s|%c=", params->tag, params->prio) < 0) { @@ -317,7 +317,7 @@ int handle_set(const struct parsed_params *params, char *config_path, struct log return copy_file_with_exceptions(config_path, &kv); } -int handle_clear(const struct parsed_params *params, char *config_path, struct log_config *conf) +int handle_clear(const struct parsed_params *params, const char *config_path, struct log_config *conf) { char *key = "limiter|"; // note: no '=' at the end, so as to match all rules const char *value = NULL; // removal @@ -331,7 +331,7 @@ int handle_clear(const struct parsed_params *params, char *config_path, struct l return copy_file_with_exceptions(config_path, &kv); } -int handle_plog(const struct parsed_params *params, char *config_path, struct log_config *conf) +int handle_plog(const struct parsed_params *params, const char *config_path, struct log_config *conf) { const int buffers_bitset = params->plog_buffers_bitset ?: ((1 << LOG_ID_MAX) - 1); @@ -366,6 +366,7 @@ int handle_plog(const struct parsed_params *params, char *config_path, struct lo return copy_file_with_exceptions(config_path, &kv); } +#ifndef UNIT_TEST static void print_limit(int limit, const char *tag, char prio, bool *shadowed, bool dynamic) { const char *const shadow_str = *shadowed ? "[shadowed] " : ""; @@ -390,7 +391,7 @@ static void print_limit(int limit, const char *tag, char prio, bool *shadowed, b *shadowed = true; } -static void get_limits(const struct parsed_params *params, char *config_path, struct log_config *conf) +static void get_limits(const struct parsed_params *params, const char *config_path, struct log_config *conf) { struct limiter_limits lims_static = __log_limiter_get_limits(params->tag, params->prio); @@ -450,7 +451,7 @@ static void print_limits_for_prio(const struct parsed_params *params, const char } } -static void get_prio_limits(const struct parsed_params *params, char *config_path, struct log_config *conf) +static void get_prio_limits(const struct parsed_params *params, const char *config_path, struct log_config *conf) { static const char prio_list[] = {'V', 'D', 'I', 'W', 'E', 'F' , 'S' , '*'}; struct prio_applies_to applies_dynamic = { .count = 0 }; @@ -472,7 +473,7 @@ static void get_prio_limits(const struct parsed_params *params, char *config_pat } -int handle_get(const struct parsed_params *params, char *config_path, struct log_config *conf) +int handle_get(const struct parsed_params *params, const char *config_path, struct log_config *conf) { if (!__log_limiter_create(conf)) { ERR("error creating limiter\n"); @@ -488,7 +489,7 @@ int handle_get(const struct parsed_params *params, char *config_path, struct log return EXIT_SUCCESS; } -int handle_dump(const struct parsed_params *params, char *config_path, struct log_config *conf) +int handle_dump(const struct parsed_params *params, const char *config_path, struct log_config *conf) { if (!__log_limiter_create(conf)) { ERR("error creating limiter\n"); @@ -524,7 +525,6 @@ int handle_dump(const struct parsed_params *params, char *config_path, struct lo return EXIT_SUCCESS; } -#ifndef UNIT_TEST int main(int argc, const char **argv) { int exit_code = EXIT_FAILURE; @@ -556,7 +556,7 @@ int main(int argc, const char **argv) return EXIT_FAILURE; } - int (*handles[])(const struct parsed_params *, char *, struct log_config *) = { + int (*handles[])(const struct parsed_params *, const char *, struct log_config *) = { [ACTION_GET] = handle_get, [ACTION_SET] = handle_set, [ACTION_DUMP] = handle_dump, @@ -567,4 +567,4 @@ int main(int argc, const char **argv) return exit_code; } -#endif +#endif // !UNIT_TEST diff --git a/src/tests/logctl.c b/src/tests/logctl.c index ecd7912..a5631d4 100644 --- a/src/tests/logctl.c +++ b/src/tests/logctl.c @@ -6,9 +6,41 @@ #include #include +static const char *const TMPFILE_PATH = "src/tests/logctl_testfile"; + +void _prepare_file(const char *const *lines, size_t lines_cnt) +{ + __attribute__((cleanup(close_FILE))) FILE *const file_prep = fopen(TMPFILE_PATH, "w"); + assert(file_prep); + + for (size_t i = 0; i < lines_cnt; ++i) { + fputs(lines[i], file_prep); + fputc('\n', file_prep); + } +} +#define PREPARE_FILE(lines) _prepare_file(lines, NELEMS(lines)) + +void _compare_file(const char *const *lines, size_t lines_cnt) +{ + __attribute__((cleanup(close_FILE))) FILE *const file_result = fopen(TMPFILE_PATH, "r"); + assert(file_result); + + char line[1024]; + size_t lines_read = 0; + while (fgets(line, sizeof line, file_result)) { + assert(lines_read < lines_cnt); + + const size_t expected_len = strlen(lines[lines_read]); + assert(line[expected_len] == '\n'); + assert(!strncmp(line, lines[lines_read], expected_len)); + + ++lines_read; + } +} +#define COMPARE_FILE(lines) _compare_file(lines, NELEMS(lines)) + void test_copy_file_with_exceptions() { - static const char *const tmpfile_path = "src/tests/logctl_testfile"; static const char *const lines_in[] = { "FOO=BAR", "FOOOO=BAZ", @@ -30,6 +62,8 @@ void test_copy_file_with_exceptions() {"QWER=", "ASDF"}, }; + PREPARE_FILE(lines_in); + struct keys_values kv = { .keys = calloc(NELEMS(kv_pairs), sizeof *kv.keys), .values = calloc(NELEMS(kv_pairs), sizeof *kv.values), @@ -42,37 +76,219 @@ void test_copy_file_with_exceptions() kv.values[i] = kv_pairs[i].value; } - FILE *const file_prep = fopen(tmpfile_path, "w"); - assert(file_prep); - for (size_t i = 0; i < NELEMS(lines_in); ++i) { - fputs(lines_in[i], file_prep); - fputc('\n', file_prep); - } - fclose(file_prep); - - const int ret = copy_file_with_exceptions(tmpfile_path, &kv); + const int ret = copy_file_with_exceptions(TMPFILE_PATH, &kv); assert(ret == EXIT_SUCCESS); - FILE *const file_result = fopen(tmpfile_path, "r"); - assert(file_result); + COMPARE_FILE(lines_out); +} - char line[1024]; - size_t lines_read = 0; - while (fgets(line, sizeof line, file_result)) { - assert(lines_read <= NELEMS(lines_out)); - if (lines_read == NELEMS(lines_out)) - continue; +void test_handle_clear() +{ + static const char *const lines_in[] = { + "limiter|x|y=BAR", + "FOOOO=BAZ", + "ABC=XYZ", + "limiter|zzz|*=15", + "ABC=ZYX", + "limiter|qwe|*=22", + "limiter|qwe|*=22", + "QWEZ=ASDX", + }; + static const char *const lines_out[] = { + "FOOOO=BAZ", + "ABC=XYZ", + "ABC=ZYX", + "QWEZ=ASDX", + }; - const size_t expected_len = strlen(lines_out[lines_read]); - assert(line[expected_len] == '\n'); - assert(!strncmp(line, lines_out[lines_read], expected_len)); + PREPARE_FILE(lines_in); + assert(EXIT_SUCCESS == handle_clear(NULL, TMPFILE_PATH, NULL)); + COMPARE_FILE(lines_out); +} - ++lines_read; - } - fclose(file_result); +void test_handle_set() +{ + static const char *const lines_in[] = { + "QWER=QWER", + "limiter|x|y=BAR", + "FOOOO=BAZ", + "limiter|z|t=FOO", + "ABC=XYZ", + }; + static const char *const lines_set[] = { + "QWER=QWER", + "FOOOO=BAZ", + "limiter|z|t=FOO", + "ABC=XYZ", + "limiter|x|y=QUUX", + }; + static const char *const lines_clear[] = { + "QWER=QWER", + "FOOOO=BAZ", + "ABC=XYZ", + "limiter|x|y=QUUX", + }; + + struct parsed_params pp; + PREPARE_FILE(lines_in); + + pp.tag = "x"; + pp.prio = 'y'; + pp.value = "QUUX"; + assert(EXIT_SUCCESS == handle_set(&pp, TMPFILE_PATH, NULL)); + COMPARE_FILE(lines_set); + + pp.tag = "z"; + pp.prio = 't'; + pp.value = NULL; + assert(EXIT_SUCCESS == handle_set(&pp, TMPFILE_PATH, NULL)); + COMPARE_FILE(lines_clear); +} + +void test_handle_plog() +{ + static const char *const lines_in[] = { + "QWER=QWER", + "enable_main=1", + "FOOOO=BAZ", + "enable_radio=0", + "ABC=XYZ", + }; + static const char *const lines_enabled[] = { + "QWER=QWER", + "FOOOO=BAZ", + "enable_radio=0", + "ABC=XYZ", + "enable_main=1", + "enable_system=1", + }; + static const char *const lines_disabled[] = { + "QWER=QWER", + "FOOOO=BAZ", + "ABC=XYZ", + "enable_system=1", + "enable_main=0", + "enable_radio=0", + }; + static const char *const lines_all[] = { + "QWER=QWER", + "FOOOO=BAZ", + "ABC=XYZ", + "enable_main=1", + "enable_radio=1", + "enable_system=1", + "enable_apps=1", + "enable_kmsg=1", + "enable_syslog=1", + }; + + struct parsed_params pp; + PREPARE_FILE(lines_in); + + pp.plog_enable = true; + pp.plog_buffers_bitset = (1 << LOG_ID_MAIN) | (1 << LOG_ID_SYSTEM); + assert(EXIT_SUCCESS == handle_plog(&pp, TMPFILE_PATH, NULL)); + COMPARE_FILE(lines_enabled); + + pp.plog_enable = false; + pp.plog_buffers_bitset = (1 << LOG_ID_MAIN) | (1 << LOG_ID_RADIO); + assert(EXIT_SUCCESS == handle_plog(&pp, TMPFILE_PATH, NULL)); + COMPARE_FILE(lines_disabled); + + pp.plog_enable = true; + pp.plog_buffers_bitset = 0; + assert(EXIT_SUCCESS == handle_plog(&pp, TMPFILE_PATH, NULL)); + COMPARE_FILE(lines_all); +} + +struct expected_opts { + int exit_code; + bool retval; + struct parsed_params pp; +}; + +void check_option_set(size_t argc, const char **argv, const struct expected_opts *exp) +{ + struct parsed_params pp = {0}; + int exit_code = 42; + bool retval = parse_options((int) argc, argv, &pp, &exit_code); + + optind = 0; + optopt = 0; + optarg = NULL; + + assert(retval == exp->retval); + assert(retval || (exit_code == exp->exit_code)); + assert(pp.action == exp->pp.action); + assert(pp.prio == exp->pp.prio); + assert(pp.plog_buffers_bitset == exp->pp.plog_buffers_bitset); + assert(pp.plog_enable == exp->pp.plog_enable); + assert(pp.value || !exp->pp.value); + assert(!pp.value || exp->pp.value); + assert(!pp.value || !strcmp(exp->pp.value, pp.value)); + assert(pp.tag || !exp->pp.tag); + assert(!pp.tag || exp->pp.tag); + assert(!pp.tag || !strcmp(exp->pp.tag, pp.tag)); +} + +void test_parse_options() +{ + /* These are primarily covered by integration tests but there's some value + * in running this at build time as well to detect any breakage ASAP. */ + + const char *none_args[] = { "x" , NULL}; + const char *garbage_args[] = { "x", "--cactus" , NULL}; + const char *clear_args[] = { "x", "-c", "-t", "tag_to_clear" , NULL}; + const char *clr_all_args[] = { "x", "-c" , NULL}; + const char *set_args[] = { "x", "-s", "15", "--priority", "e" , NULL}; + const char *get_args[] = { "x", "-g", "-p", "*", "-t", "*" , NULL}; + const char *dump_args[] = { "x", "-g" , NULL}; + const char *enable_args[] = { "x", "--enable", "-b", "main", "-b", "radio", NULL}; + const char *disable_args[] = { "x", "--disable", "-b", "main", "-b", "radio", NULL}; + const char *help_args[] = { "x", "--help" , NULL}; + + const char *prio_err_args[] = { "x", "--priority", "]" , NULL}; + const char *buf_err_args[] = { "x", "--buffer", "invalid" , NULL}; + const char *plog_err_args[] = { "x", "-g", "--buffer", "main" , NULL}; + + static const struct expected_opts none_opts = { EXIT_SUCCESS, false, { ACTION_NONE , "*" , '\0', NULL, false, 0 } }; + static const struct expected_opts garbage_opts = { EXIT_SUCCESS, false, { ACTION_NONE , "*" , '\0', NULL, false, 0 } }; + static const struct expected_opts clear_opts = { EXIT_SUCCESS, true , { ACTION_SET , "tag_to_clear", '*', NULL, false, 0 } }; + static const struct expected_opts clr_all_opts = { EXIT_SUCCESS, true , { ACTION_CLEAR, "*" , '\0', NULL, false, 0 } }; + static const struct expected_opts set_opts = { EXIT_SUCCESS, true , { ACTION_SET , "*" , 'E', "15", false, 0 } }; + static const struct expected_opts get_opts = { EXIT_SUCCESS, true , { ACTION_GET , "*" , '*', NULL, false, 0 } }; + static const struct expected_opts dump_opts = { EXIT_SUCCESS, true , { ACTION_DUMP , "*" , '\0', NULL, false, 0 } }; + static const struct expected_opts enable_opts = { EXIT_SUCCESS, true , { ACTION_PLOG , "*" , '\0', NULL, true , 1 << LOG_ID_MAIN | 1 << LOG_ID_RADIO } }; + static const struct expected_opts disable_opts = { EXIT_SUCCESS, true , { ACTION_PLOG , "*" , '\0', NULL, false, 1 << LOG_ID_MAIN | 1 << LOG_ID_RADIO } }; + static const struct expected_opts help_opts = { EXIT_SUCCESS, false, { ACTION_NONE , "*" , '\0', NULL, false, 0 } }; + + static const struct expected_opts prio_err_opts = { EXIT_FAILURE, false, { ACTION_NONE , "*" , ']', NULL, false, 0 } }; + static const struct expected_opts buf_err_opts = { EXIT_FAILURE, false, { ACTION_NONE , "*" , '\0', NULL, false, 0 } }; + static const struct expected_opts plog_err_opts = { EXIT_FAILURE, false, { ACTION_GET , "*" , '\0', NULL, false, 1 << LOG_ID_MAIN } }; + +#define CHECK_OPTION_SET(TYPE) check_option_set(NELEMS(TYPE##_args) - 1, TYPE##_args, &(TYPE##_opts)) + CHECK_OPTION_SET(none); + CHECK_OPTION_SET(garbage); + CHECK_OPTION_SET(clear); + CHECK_OPTION_SET(clr_all); + CHECK_OPTION_SET(set); + CHECK_OPTION_SET(get); + CHECK_OPTION_SET(dump); + CHECK_OPTION_SET(enable); + CHECK_OPTION_SET(disable); + CHECK_OPTION_SET(help); + + CHECK_OPTION_SET(prio_err); + CHECK_OPTION_SET(buf_err); + CHECK_OPTION_SET(plog_err); +#undef CHECK_OPTION_SET } int main() { test_copy_file_with_exceptions(); + test_parse_options(); + test_handle_clear(); + test_handle_set(); + test_handle_plog(); }