]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
config: Add unit test for config parser
authorAki Tuomi <aki.tuomi@open-xchange.com>
Mon, 25 Jan 2021 11:32:18 +0000 (13:32 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 3 Feb 2021 08:00:29 +0000 (08:00 +0000)
src/config/Makefile.am
src/config/test-config-parser.c [new file with mode: 0644]

index e38fac1b6a070b91241042e09bd36b6706069e5c..084ec0ed98f6832f8dd4bc27a41b4921214de778 100644 (file)
@@ -7,6 +7,7 @@ pkglibexec_PROGRAMS = config
 
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib \
+       -I$(top_srcdir)/src/lib-test \
        -I$(top_srcdir)/src/lib-dns \
        -I$(top_srcdir)/src/lib-mail \
        -I$(top_srcdir)/src/lib-settings \
@@ -76,3 +77,22 @@ all-settings.c: $(SETTING_FILES) $(top_srcdir)/src/config/settings-get.pl
 EXTRA_DIST = \
        config-settings.c \
        settings-get.pl
+
+test_programs = \
+       test-config-parser
+
+noinst_PROGRAMS = $(test_programs)
+
+test_libs = \
+       $(noinst_LTLIBRARIES) \
+       $(LIBDOVECOT)
+
+test_config_parser_CFLAGS = $(AM_CPPFLAGS)
+test_config_parser_SOURCES = test-config-parser.c
+test_config_parser_LDADD = $(test_libs)
+test_config_parser_DEPENDENCIES = $(LIBDOVECOT_DEPS) $(noinst_LTLIBRARIES)
+
+check-local:
+       for bin in $(test_programs); do \
+         if ! $(RUN_TEST) ./$$bin; then exit 1; fi; \
+       done
diff --git a/src/config/test-config-parser.c b/src/config/test-config-parser.c
new file mode 100644 (file)
index 0000000..0f842c8
--- /dev/null
@@ -0,0 +1,169 @@
+/* Copyright (c) 2021 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ostream.h"
+#include "service-settings.h"
+#include "settings-parser.h"
+#include "config-filter.h"
+#include "test-common.h"
+#include "all-settings.h"
+#include "config-parser.h"
+
+#define TEST_CONFIG_FILE ".test_config"
+
+static ARRAY_TYPE(service_settings) services = ARRAY_INIT;
+ARRAY_TYPE(service_settings) *default_services = &services;
+
+struct test_settings {
+       const char *key;
+       const char *key2;
+       const char *key3;
+       const char *key4;
+       const char *key5;
+       const char *pop3_deleted_flag;
+       const char *env_key;
+       const char *env_key2;
+       const char *env_key3;
+       const char *env_key4;
+       const char *env_key5;
+       const char *protocols;
+};
+
+static const struct setting_define test_settings_defs[] = {
+       SETTING_DEFINE_STRUCT_STR(key, test_settings),
+       SETTING_DEFINE_STRUCT_STR(key2, test_settings),
+       SETTING_DEFINE_STRUCT_STR(key3, test_settings),
+       SETTING_DEFINE_STRUCT_STR(key4, test_settings),
+       SETTING_DEFINE_STRUCT_STR(key5, test_settings),
+       SETTING_DEFINE_STRUCT_STR(pop3_deleted_flag, test_settings),
+       SETTING_DEFINE_STRUCT_STR(env_key, test_settings),
+       SETTING_DEFINE_STRUCT_STR(env_key2, test_settings),
+       SETTING_DEFINE_STRUCT_STR(env_key3, test_settings),
+       SETTING_DEFINE_STRUCT_STR(env_key4, test_settings),
+       SETTING_DEFINE_STRUCT_STR(env_key5, test_settings),
+       SETTING_DEFINE_STRUCT_STR(protocols, test_settings),
+       SETTING_DEFINE_LIST_END
+};
+
+static const struct test_settings test_settings_defaults = {
+       .key = "",
+       .key2 = "",
+       .key3 = "",
+       .key4 = "",
+       .key5 = "",
+       .pop3_deleted_flag = "",
+       .env_key = "",
+       .env_key2 = "",
+       .env_key3 = "",
+       .env_key4 = "",
+       .env_key5 = "",
+       .protocols = "pop3",
+};
+
+const struct setting_parser_info test_settings_root = {
+       .module_name = "test",
+       .defines = test_settings_defs,
+       .defaults = &test_settings_defaults,
+
+       .type_offset = SIZE_MAX,
+       .struct_size = sizeof(struct test_settings),
+
+       .parent_offset = SIZE_MAX,
+       .parent = NULL,
+};
+
+static const struct setting_parser_info *const roots[] = {
+       &test_settings_root,
+       NULL
+};
+
+const struct setting_parser_info *const *all_roots = roots;
+
+static void write_config_file(const char *contents)
+{
+       struct ostream *os = o_stream_create_file(TEST_CONFIG_FILE, 0, 0600, 0);
+       o_stream_nsend_str(os, contents);
+       test_assert(o_stream_finish(os) == 1);
+       o_stream_unref(&os);
+}
+
+static void test_config_parser(void)
+{
+       const char *error = NULL;
+
+       test_begin("config_parse_file");
+
+       write_config_file(
+"# comment\n"
+"key=value\n"
+"key2 = \\$escape \\escape \\\"escape\\\"\n"
+"key3 = value\n"
+"key3 = $key3 nothervalue\n"
+"key3 = yetanother value $key3 right here\n"
+"key4 = \" $key3 \"\n"
+"key5 = ' $key4 '\n"
+"pop3_deleted_flag = \"$Deleted\"\n"
+"env_key=$ENV:foo\n"
+"env_key=$env_key $ENV:bar\n"
+"env_key=$env_key \"$env_key\"\n"
+"env_key2 = foo$ENV:FOO bar\n"
+"env_key3 = $ENV:FOO$ENV:FOO bar\n"
+"env_key4 = $ENV:foo $ENV:bar $key\n"
+"env_key5 = $ENV:foo $ENV:foo\n"
+"protocols = $protocols imap\n"
+       );
+
+       putenv("foo=test1");
+       putenv("bar=test2");
+       putenv("FOO$ENV:FOO=works");
+
+       test_assert(config_parse_file(TEST_CONFIG_FILE, TRUE, NULL, &error) == 1);
+       if (error != NULL)
+               i_error("config_parse_file(): %s", error);
+
+       /* get the parsed output */
+       const struct test_settings *set =
+               settings_parser_get(config_module_parsers[0].parser);
+       test_assert_strcmp(set->key, "value");
+       test_assert_strcmp(set->key2, "\\$escape \\escape \\\"escape\\\"");
+       test_assert_strcmp(set->key3, "yetanother value value nothervalue right here");
+       test_assert_strcmp(set->key4, " $key3 ");
+       test_assert_strcmp(set->key5, " $key4 ");
+       test_assert_strcmp(set->pop3_deleted_flag, "$Deleted");
+       test_assert_strcmp(set->env_key, "test1 test2 \"$env_key\"");
+       test_assert_strcmp(set->env_key2, "foo$ENV:FOO bar");
+       test_assert_strcmp(set->env_key3, "works bar");
+       test_assert_strcmp(set->env_key4, "test1 test2 value");
+       test_assert_strcmp(set->env_key5, "test1 test1");
+       test_assert_strcmp(set->protocols, "pop3 imap");
+
+       /* try again unexpanded */
+       test_assert(config_parse_file(TEST_CONFIG_FILE, FALSE, NULL, &error) == 1);
+       set = settings_parser_get(config_module_parsers[0].parser);
+
+       test_assert_strcmp(set->key, "value");
+       test_assert_strcmp(set->key2, "\\$escape \\escape \\\"escape\\\"");
+       test_assert_strcmp(set->key3, "yetanother value value nothervalue right here");
+       test_assert_strcmp(set->key4, " $key3 ");
+       test_assert_strcmp(set->key5, " $key4 ");
+       test_assert_strcmp(set->pop3_deleted_flag, "$Deleted");
+       test_assert_strcmp(set->env_key, "$ENV:foo $ENV:bar \"$env_key\"");
+       test_assert_strcmp(set->env_key2, "foo$ENV:FOO bar");
+       test_assert_strcmp(set->env_key3, "$ENV:FOO$ENV:FOO bar");
+       test_assert_strcmp(set->env_key4, "$ENV:foo $ENV:bar $key");
+       test_assert_strcmp(set->env_key5, "$ENV:foo $ENV:foo");
+       test_assert_strcmp(set->protocols, "pop3 imap");
+
+       config_filter_deinit(&config_filter);
+       config_parser_deinit();
+       test_end();
+}
+
+int main(void)
+{
+       static void (*const test_functions[])(void) = {
+               test_config_parser,
+               NULL
+       };
+       return test_run(test_functions);
+}