From: Richard Russon Date: Fri, 19 Apr 2019 16:49:29 +0000 (+0100) Subject: test: add coverage of config dump functions X-Git-Tag: 2019-10-25~247^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c6b70157a3a5ed8c1c1923dbe89557c8857a5369;p=neomutt test: add coverage of config dump functions --- diff --git a/Makefile.autosetup b/Makefile.autosetup index 7864aa796..356167865 100644 --- a/Makefile.autosetup +++ b/Makefile.autosetup @@ -446,7 +446,6 @@ distclean: clean # coverage testing coverage: all test $(RM) lcov - $(RM) config/dump.gc?? lcov -t "test" -o lcov.info -c -d mutt -d config -genhtml -o lcov lcov.info -f lcov -l lcov.info diff --git a/config/dump.c b/config/dump.c index 9077baeeb..e3572eb1a 100644 --- a/config/dump.c +++ b/config/dump.c @@ -36,7 +36,7 @@ #include "set.h" #include "types.h" -void mutt_pretty_mailbox(char *s, size_t buflen); +void mutt_pretty_mailbox(char *buf, size_t buflen); /** * escape_string - Write a string to a buffer, escaping special characters @@ -102,6 +102,9 @@ size_t pretty_var(const char *str, struct Buffer *buf) */ int elem_list_sort(const void *a, const void *b) { + if (!a || !b) + return 0; + const struct HashElem *hea = *(struct HashElem **) a; const struct HashElem *heb = *(struct HashElem **) b; @@ -129,10 +132,7 @@ struct HashElem **get_elem_list(struct ConfigSet *cs) { list[index++] = he; if (index == 1022) - { - mutt_debug(LL_DEBUG1, "Too many config items to sort\n"); - break; - } + break; /* LCOV_EXCL_LINE */ } qsort(list, index, sizeof(struct HashElem *), elem_list_sort); @@ -152,6 +152,9 @@ struct HashElem **get_elem_list(struct ConfigSet *cs) void dump_config_mutt(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value, struct Buffer *initial, ConfigDumpFlags flags, FILE *fp) { + if (!he || !value || !fp) + return; + const char *name = he->key.strkey; if (DTYPE(he->type) == DT_BOOL) @@ -183,6 +186,9 @@ void dump_config_mutt(struct ConfigSet *cs, struct HashElem *he, struct Buffer * void dump_config_neo(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value, struct Buffer *initial, ConfigDumpFlags flags, FILE *fp) { + if (!he || !value || !initial || !fp) + return; + const char *name = he->key.strkey; if ((flags & CS_DUMP_ONLY_CHANGED) && (mutt_str_strcmp(value->data, initial->data) == 0)) @@ -235,7 +241,7 @@ bool dump_config(struct ConfigSet *cs, enum CsDumpStyle style, struct HashElem **list = get_elem_list(cs); if (!list) - return false; + return false; /* LCOV_EXCL_LINE */ bool result = true; @@ -265,8 +271,8 @@ bool dump_config(struct ConfigSet *cs, enum CsDumpStyle style, int rc = cs_he_string_get(cs, he, value); if (CSR_RESULT(rc) != CSR_SUCCESS) { - result = false; - break; + result = false; /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ } const struct ConfigDef *cdef = he->data; @@ -295,8 +301,8 @@ bool dump_config(struct ConfigSet *cs, enum CsDumpStyle style, int rc = cs_he_initial_get(cs, he, initial); if (CSR_RESULT(rc) != CSR_SUCCESS) { - result = false; - break; + result = false; /* LCOV_EXCL_LINE */ + break; /* LCOV_EXCL_LINE */ } if ((type == DT_PATH) && !(he->type & DT_MAILBOX)) diff --git a/muttlib.h b/muttlib.h index 68fa02572..398ba031a 100644 --- a/muttlib.h +++ b/muttlib.h @@ -62,7 +62,7 @@ bool mutt_matches_ignore(const char *s); void mutt_mktemp_full(char *s, size_t slen, const char *prefix, const char *suffix, const char *src, int line); bool mutt_needs_mailcap(struct Body *m); FILE * mutt_open_read(const char *path, pid_t *thepid); -void mutt_pretty_mailbox(char *s, size_t buflen); +void mutt_pretty_mailbox(char *buf, size_t buflen); uint32_t mutt_rand32(void); uint64_t mutt_rand64(void); void mutt_rand_base32(void *out, size_t len); diff --git a/test/Makefile.autosetup b/test/Makefile.autosetup index 9e0829524..98a40bb57 100644 --- a/test/Makefile.autosetup +++ b/test/Makefile.autosetup @@ -9,7 +9,7 @@ TEST_OBJS = test/main.o \ CONFIG_OBJS = test/config/main.o test/config/account.o \ test/config/address.o test/config/bool.o \ - test/config/command.o test/config/common.o \ + test/config/command.o test/config/common.o test/config/dump.o \ test/config/initial.o test/config/long.o \ test/config/magic.o test/config/mbtable.o \ test/config/number.o test/config/path.o test/config/quad.o \ diff --git a/test/config/dump.c b/test/config/dump.c new file mode 100644 index 000000000..05e89dfe3 --- /dev/null +++ b/test/config/dump.c @@ -0,0 +1,368 @@ +/** + * @file + * Test code for the Config Dump functions + * + * @authors + * Copyright (C) 2017-2018 Richard Russon + * + * @copyright + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#define TEST_NO_MAIN +#include "acutest.h" +#include "config.h" +#include "mutt/mutt.h" +#include "config/common.h" +#include "config/lib.h" + +static bool VarApple; +static bool VarBanana; +static short VarCherry; +static struct Address *VarElderberry; +static char *VarFig; +static long VarGuava; +static short VarHawthorn; +static struct MbTable *VarIlama; +static char *VarJackfruit; +static char VarKumquat; +static struct Regex *VarLemon; +static short VarMango; +static char *VarNectarine; + +// clang-format off +static struct ConfigDef Vars[] = { + { "Apple", DT_BOOL, 0, &VarApple, false, NULL }, + { "Banana", DT_BOOL, 0, &VarBanana, true, NULL }, + { "Cherry", DT_NUMBER, 0, &VarCherry, 0, NULL }, + { "Damson", DT_SYNONYM, 0, NULL, IP "Cherry", NULL }, + { "Elderberry", DT_ADDRESS, 0, &VarElderberry, IP "elderberry@example.com", NULL }, + { "Fig", DT_COMMAND|DT_NOT_EMPTY, 0, &VarFig, IP "fig", NULL }, + { "Guava", DT_LONG, 0, &VarGuava, 0, NULL }, + { "Hawthorn", DT_MAGIC, 0, &VarHawthorn, 1, NULL }, + { "Ilama", DT_MBTABLE, 0, &VarIlama, 0, NULL }, + { "Jackfruit", DT_PATH, 0, &VarJackfruit, IP "/etc/passwd", NULL }, + { "Kumquat", DT_QUAD, 0, &VarKumquat, 0, NULL }, + { "Lemon", DT_REGEX, 0, &VarLemon, 0, NULL }, + { "Mango", DT_SORT, 0, &VarMango, 1, NULL }, + { "Nectarine", DT_STRING, F_SENSITIVE, &VarNectarine, IP "nectarine", NULL }, + { NULL }, +}; +// clang-format on + +void mutt_pretty_mailbox(char *buf, size_t buflen) +{ +} + +bool test_pretty_var(void) +{ + // size_t pretty_var(const char *str, struct Buffer *buf); + + { + struct Buffer buf = { 0 }; + if (!TEST_CHECK(pretty_var(NULL, &buf) == 0)) + return false; + } + + { + if (!TEST_CHECK(pretty_var("apple", NULL) == 0)) + return false; + } + + { + struct Buffer *buf = mutt_buffer_alloc(64); + if (!TEST_CHECK(pretty_var("apple", buf) > 0)) + { + mutt_buffer_free(&buf); + return false; + } + + if (!TEST_CHECK(mutt_str_strcmp("\"apple\"", mutt_b2s(buf)) == 0)) + { + mutt_buffer_free(&buf); + return false; + } + + mutt_buffer_free(&buf); + } + + return true; +} + +bool test_escape_string(void) +{ + // size_t escape_string(struct Buffer *buf, const char *src); + + { + if (!TEST_CHECK(escape_string(NULL, "apple") == 0)) + return false; + } + + { + struct Buffer buf = { 0 }; + if (!TEST_CHECK(escape_string(&buf, NULL) == 0)) + return false; + } + + { + const char *before = "apple\nbanana\rcherry\tdamson\\endive\"fig'grape"; + const char *after = "apple\\nbanana\\rcherry\\tdamson\\\\endive\\\"fig'grape"; + struct Buffer *buf = mutt_buffer_alloc(256); + if (!TEST_CHECK(escape_string(buf, before) > 0)) + { + mutt_buffer_free(&buf); + return false; + } + + if (!TEST_CHECK(mutt_str_strcmp(mutt_b2s(buf), after) == 0)) + { + mutt_buffer_free(&buf); + return false; + } + + mutt_buffer_free(&buf); + } + + return true; +} + +bool test_elem_list_sort(void) +{ + // int elem_list_sort(const void *a, const void *b); + + { + struct HashElem he = { 0 }; + if (!TEST_CHECK(elem_list_sort(NULL, &he) == 0)) + return false; + } + + { + struct HashElem he = { 0 }; + if (!TEST_CHECK(elem_list_sort(&he, NULL) == 0)) + return false; + } + + return true; +} + +struct ConfigSet *create_sample_data(void) +{ + struct ConfigSet *cs = cs_new(30); + if (!cs) + return NULL; + + address_init(cs); + bool_init(cs); + command_init(cs); + long_init(cs); + magic_init(cs); + mbtable_init(cs); + number_init(cs); + path_init(cs); + quad_init(cs); + regex_init(cs); + sort_init(cs); + string_init(cs); + + if (!cs_register_variables(cs, Vars, 0)) + return NULL; + + return cs; +} + +bool test_get_elem_list(void) +{ + // struct HashElem **get_elem_list(struct ConfigSet *cs); + + { + if (!TEST_CHECK(get_elem_list(NULL) == NULL)) + return false; + } + + { + struct ConfigSet *cs = create_sample_data(); + if (!cs) + return false; + + struct HashElem **list = NULL; + if (!TEST_CHECK((list = get_elem_list(cs)) != NULL)) + { + cs_free(&cs); + return false; + } + + FREE(&list); + cs_free(&cs); + } + + return true; +} + +bool test_dump_config_mutt(void) +{ + // void dump_config_mutt(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value, struct Buffer *initial, ConfigDumpFlags flags, FILE *fp); + + { + struct ConfigSet *cs = create_sample_data(); + if (!cs) + return false; + + struct HashElem *he = cs_get_elem(cs, "Apple"); + + struct Buffer *buf_val = mutt_buffer_from("yes"); + struct Buffer *buf_init = mutt_buffer_from("initial"); + + // Degenerate tests + + dump_config_mutt(NULL, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_mutt(NULL, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout)"); + dump_config_mutt(cs, NULL, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_mutt(cs, NULL, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout)"); + dump_config_mutt(cs, he, NULL, buf_init, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_mutt(cs, he, NULL, buf_init, CS_DUMP_NO_FLAGS, stdout)"); + dump_config_mutt(cs, he, buf_val, NULL, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_mutt(cs, he, buf_val, NULL, CS_DUMP_NO_FLAGS, stdout)"); + dump_config_mutt(cs, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, NULL); + TEST_CHECK_(1, "dump_config_mutt(cs, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, NULL)"); + + // Normal tests + + dump_config_mutt(cs, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_mutt(cs, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout)"); + + mutt_buffer_reset(buf_val); + mutt_buffer_addstr(buf_val, "no"); + + dump_config_mutt(cs, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_mutt(NULL, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout)"); + + he = cs_get_elem(cs, "Cherry"); + + dump_config_mutt(cs, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_mutt(NULL, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout)"); + + mutt_buffer_free(&buf_val); + mutt_buffer_free(&buf_init); + cs_free(&cs); + } + + return true; +} + +bool test_dump_config_neo(void) +{ + // void dump_config_neo(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value, struct Buffer *initial, ConfigDumpFlags flags, FILE *fp); + + { + struct ConfigSet *cs = create_sample_data(); + if (!cs) + return false; + + struct HashElem *he = cs_get_elem(cs, "Banana"); + + struct Buffer *buf_val = mutt_buffer_from("yes"); + struct Buffer *buf_init = mutt_buffer_from("yes"); + + // Degenerate tests + + dump_config_neo(NULL, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_neo(NULL, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout)"); + dump_config_neo(cs, NULL, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_neo(cs, NULL, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout)"); + dump_config_neo(cs, he, NULL, buf_init, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_neo(cs, he, NULL, buf_init, CS_DUMP_NO_FLAGS, stdout)"); + dump_config_neo(cs, he, buf_val, NULL, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_neo(cs, he, buf_val, NULL, CS_DUMP_NO_FLAGS, stdout)"); + dump_config_neo(cs, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, NULL); + TEST_CHECK_(1, "dump_config_neo(cs, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, NULL)"); + + // Normal tests + + dump_config_neo(cs, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_neo(cs, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout)"); + + dump_config_neo(cs, he, buf_val, buf_init, CS_DUMP_ONLY_CHANGED, stdout); + TEST_CHECK_(1, "dump_config_neo(cs, he, buf_val, buf_init, CS_DUMP_ONLY_CHANGED, stdout)"); + + dump_config_neo(cs, he, buf_val, buf_init, CS_DUMP_SHOW_DEFAULTS, stdout); + TEST_CHECK_(1, "dump_config_neo(cs, he, buf_val, buf_init, CS_DUMP_SHOW_DEFAULTS, stdout)"); + + he = mutt_hash_find_elem(cs->hash, "Damson"); + dump_config_neo(cs, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout); + TEST_CHECK_(1, "dump_config_neo(cs, he, buf_val, buf_init, CS_DUMP_NO_FLAGS, stdout)"); + + mutt_buffer_free(&buf_val); + mutt_buffer_free(&buf_init); + cs_free(&cs); + } + + return true; +} + +bool test_dump_config(void) +{ + // bool dump_config(struct ConfigSet *cs, enum CsDumpStyle style, ConfigDumpFlags flags, FILE *fp); + + { + struct ConfigSet *cs = create_sample_data(); + if (!cs) + return false; + + // Degenerate tests + + if (!TEST_CHECK(dump_config(NULL, CS_DUMP_STYLE_NEO, CS_DUMP_NO_FLAGS, stdout) == false)) + return false; + if (!TEST_CHECK(dump_config(cs, CS_DUMP_STYLE_NEO, CS_DUMP_NO_FLAGS, NULL) == true)) + return false; + + // Normal tests + + if (!TEST_CHECK(dump_config(cs, CS_DUMP_STYLE_MUTT, CS_DUMP_NO_FLAGS, stdout) == true)) + return false; + if (!TEST_CHECK(dump_config(cs, CS_DUMP_STYLE_NEO, CS_DUMP_NO_FLAGS, stdout) == true)) + return false; + if (!TEST_CHECK(dump_config(cs, CS_DUMP_STYLE_NEO, CS_DUMP_ONLY_CHANGED|CS_DUMP_HIDE_SENSITIVE, stdout) == true)) + return false; + if (!TEST_CHECK(dump_config(cs, CS_DUMP_STYLE_NEO, CS_DUMP_HIDE_VALUE|CS_DUMP_SHOW_DEFAULTS, stdout) == true)) + return false; + + struct ConfigSet *cs_bad = cs_new(30); + if (!TEST_CHECK(dump_config(cs_bad, CS_DUMP_STYLE_NEO, CS_DUMP_NO_FLAGS, stdout) == true)) + return false; + + cs_free(&cs_bad); + cs_free(&cs); + } + + return true; +} + +void config_dump(void) +{ + if (!test_pretty_var()) + return; + if (!test_escape_string()) + return; + if (!test_elem_list_sort()) + return; + if (!test_get_elem_list()) + return; + if (!test_dump_config_mutt()) + return; + if (!test_dump_config_neo()) + return; + if (!test_dump_config()) + return; +} + diff --git a/test/config/main.c b/test/config/main.c index 49676336d..9b3b80c8d 100644 --- a/test/config/main.c +++ b/test/config/main.c @@ -64,7 +64,8 @@ NEOMUTT_TEST_ITEM(config_quad) \ NEOMUTT_TEST_ITEM(config_regex) \ NEOMUTT_TEST_ITEM(config_sort) \ - NEOMUTT_TEST_ITEM(config_string) + NEOMUTT_TEST_ITEM(config_string) \ + NEOMUTT_TEST_ITEM(config_dump) /****************************************************************************** * You probably don't need to touch what follows.