]> granicus.if.org Git - neomutt/commitdiff
test: add coverage of config dump functions
authorRichard Russon <rich@flatcap.org>
Fri, 19 Apr 2019 16:49:29 +0000 (17:49 +0100)
committerRichard Russon <rich@flatcap.org>
Wed, 24 Apr 2019 11:16:16 +0000 (12:16 +0100)
Makefile.autosetup
config/dump.c
muttlib.h
test/Makefile.autosetup
test/config/dump.c [new file with mode: 0644]
test/config/main.c

index 7864aa7960ec0046068042af05e2bc30cb5d91bb..3561678656a50c8a56050d573fc8e5245ba01b07 100644 (file)
@@ -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
index 9077baeeb9b205facb789ba1e9583132b6ef83ee..e3572eb1af87f1953e8346a5019d0c07577cfd05 100644 (file)
@@ -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))
index 68fa0257230b1e40d91fb5bd6b57b1ff93a2c36c..398ba031a14d3ce8a038bcb2c7fb10aaab721ee5 100644 (file)
--- 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);
index 9e0829524242574b3f046399cbbac28630f6d1ae..98a40bb57374d000d46ebc7a58b9581a38ebd106 100644 (file)
@@ -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 (file)
index 0000000..05e89df
--- /dev/null
@@ -0,0 +1,368 @@
+/**
+ * @file
+ * Test code for the Config Dump functions
+ *
+ * @authors
+ * Copyright (C) 2017-2018 Richard Russon <rich@flatcap.org>
+ *
+ * @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 <http://www.gnu.org/licenses/>.
+ */
+
+#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;
+}
+
index 49676336d98ce2679cdb02fcb7cc406b2ca99138..9b3b80c8d8f8bd93c6e6b4542a94343cd31f4b4b 100644 (file)
@@ -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.