diff options
Diffstat (limited to 'src/lib-settings/test-settings-parser.c')
-rw-r--r-- | src/lib-settings/test-settings-parser.c | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/src/lib-settings/test-settings-parser.c b/src/lib-settings/test-settings-parser.c new file mode 100644 index 0000000..83aefba --- /dev/null +++ b/src/lib-settings/test-settings-parser.c @@ -0,0 +1,340 @@ +/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "net.h" +#include "var-expand.h" +#include "settings-parser.h" +#include "istream.h" +#include "test-common.h" + +static const char *test_settings_blobs[] = +{ +/* Blob 0 */ + "bool_true=yes\n" + "bool_false=no\n" + "uint=15\n" + "uint_oct=0700\n" + "secs=5s\n" + "msecs=5ms\n" + "size=1k\n" + "port=2205\n" + "str=test string\n" + "expand_str=test %{string}\n" + "strlist=\n" + "strlist/x=a\n" + "strlist/y=b\n" + "strlist/z=c\n" + "\n", +}; + + +static void test_settings_get_time(void) +{ + static const struct { + const char *input; + unsigned int output; + } tests[] = { + { "0", 0 }, + + { "59s", 59 }, + { "59 s", 59 }, + { "59se", 59 }, + { "59sec", 59 }, + { "59secs", 59 }, + { "59seco", 59 }, + { "59secon", 59 }, + { "59second", 59 }, + { "59seconds", 59 }, + { "123456 seconds", 123456 }, + + { "123m", 123*60 }, + { "123 m", 123*60 }, + { "123 mi", 123*60 }, + { "123 min", 123*60 }, + { "123 mins", 123*60 }, + { "123 minu", 123*60 }, + { "123 minut", 123*60 }, + { "123 minute", 123*60 }, + { "123 minutes", 123*60 }, + + { "123h", 123*60*60 }, + { "123 h", 123*60*60 }, + { "123 ho", 123*60*60 }, + { "123 hou", 123*60*60 }, + { "123 hour", 123*60*60 }, + { "123 hours", 123*60*60 }, + + { "12d", 12*60*60*24 }, + { "12 d", 12*60*60*24 }, + { "12 da", 12*60*60*24 }, + { "12 day", 12*60*60*24 }, + { "12 days", 12*60*60*24 }, + + { "3w", 3*60*60*24*7 }, + { "3 w", 3*60*60*24*7 }, + { "3 we", 3*60*60*24*7 }, + { "3 wee", 3*60*60*24*7 }, + { "3 week", 3*60*60*24*7 }, + { "3 weeks", 3*60*60*24*7 }, + + { "1000ms", 1 }, + { "50000ms", 50 }, + }; + struct { + const char *input; + unsigned int output; + } msecs_tests[] = { + { "0ms", 0 }, + { "1ms", 1 }, + { "123456ms", 123456 }, + { "123456 ms", 123456 }, + { "123456mse", 123456 }, + { "123456msec", 123456 }, + { "123456msecs", 123456 }, + { "123456mseco", 123456 }, + { "123456msecon", 123456 }, + { "123456msecond", 123456 }, + { "123456mseconds", 123456 }, + { "123456mil", 123456 }, + { "123456mill", 123456 }, + { "123456milli", 123456 }, + { "123456millis", 123456 }, + { "123456millisec", 123456 }, + { "123456millisecs", 123456 }, + { "123456milliseco", 123456 }, + { "123456millisecon", 123456 }, + { "123456millisecond", 123456 }, + { "123456milliseconds", 123456 }, + { "4294967295 ms", 4294967295 }, + }; + const char *secs_errors[] = { + "-1", + "1", + /* wrong spellings: */ + "1ss", + "1secss", + "1secondss", + "1ma", + "1minsa", + "1hu", + "1hoursa", + "1dd", + "1days?", + "1wa", + "1weeksb", + + /* milliseconds: */ + "1ms", + "999ms", + "1001ms", + /* overflows: */ + "7102 w", + "4294967296 s", + }; + const char *msecs_errors[] = { + "-1", + "1", + /* wrong spellings: */ + "1mis", + "1mss", + /* overflows: */ + "8 w", + "4294967296 ms", + }; + unsigned int i, secs, msecs; + const char *error; + + test_begin("settings_get_time()"); + for (i = 0; i < N_ELEMENTS(tests); i++) { + test_assert_idx(settings_get_time(tests[i].input, &secs, &error) == 0, i); + test_assert_idx(secs == tests[i].output, i); + + test_assert_idx(settings_get_time_msecs(tests[i].input, &msecs, &error) == 0, i); + test_assert_idx(msecs == tests[i].output*1000, i); + } + for (i = 0; i < N_ELEMENTS(msecs_tests); i++) { + test_assert_idx(settings_get_time_msecs(msecs_tests[i].input, &msecs, &error) == 0, i); + test_assert_idx(msecs == msecs_tests[i].output, i); + } + for (i = 0; i < N_ELEMENTS(secs_errors); i++) + test_assert_idx(settings_get_time(secs_errors[i], &secs, &error) < 0, i); + for (i = 0; i < N_ELEMENTS(msecs_errors); i++) + test_assert_idx(settings_get_time_msecs(msecs_errors[i], &msecs, &error) < 0, i); + test_end(); +} + +static void test_settings_get_size(void) +{ + test_begin("settings_get_size()"); + + static const struct { + const char *input; + uoff_t output; + } tests[] = { + { "0", 0 }, + { "0000", 0 }, + { "1b", 1 }, + { "1B", 1 }, + { "1 b", 1 }, + { "1k", 1024 }, + { "1K", 1024 }, + { "1 k", 1024 }, + { "1m", 1024*1024 }, + { "1M", 1024*1024 }, + { "1 m", 1024*1024 }, + { "1g", 1024*1024*1024ULL }, + { "1G", 1024*1024*1024ULL }, + { "1 g", 1024*1024*1024ULL }, + { "1t", 1024*1024*1024*1024ULL }, + { "1T", 1024*1024*1024*1024ULL }, + { "1 t", 1024*1024*1024*1024ULL }, + }; + + const char *size_errors[] = { + "-1", + "one", + "", + "340282366920938463463374607431768211456", + "2^32", + "2**32", + "1e10", + "1 byte", + }; + + size_t i; + uoff_t size; + const char *error; + + for (i = 0; i < N_ELEMENTS(tests); i++) { + error = NULL; + test_assert_idx(settings_get_size(tests[i].input, &size, &error) == 0, i); + test_assert_idx(size == tests[i].output, i); + test_assert(error == NULL); + } + for (i = 0; i < N_ELEMENTS(size_errors); i++) { + error = NULL; + test_assert_idx(settings_get_size(size_errors[i], &size, &error) < 0, i); + test_assert(error != NULL); + }; + + test_end(); +} + +static void test_settings_parser_get(void) +{ + struct test_settings { + bool bool_true; + bool bool_false; + unsigned int uint; + unsigned int uint_oct; + unsigned int secs; + unsigned int msecs; + uoff_t size; + in_port_t port; + const char *str; + const char *expand_str; + ARRAY_TYPE(const_string) strlist; + } test_defaults = { + FALSE, /* for negation test */ + TRUE, + 0, + 0, + 0, + 0, + 0, + 0, + "", + "", + ARRAY_INIT, + }; + const struct setting_define defs[] = { + SETTING_DEFINE_STRUCT_BOOL("bool_true", bool_true, struct test_settings), + SETTING_DEFINE_STRUCT_BOOL("bool_false", bool_false, struct test_settings), + SETTING_DEFINE_STRUCT_UINT("uint", uint, struct test_settings), + { .type = SET_UINT_OCT, .key = "uint_oct", + offsetof(struct test_settings, uint_oct), NULL }, + SETTING_DEFINE_STRUCT_TIME("secs", secs, struct test_settings), + SETTING_DEFINE_STRUCT_TIME_MSECS("msecs", msecs, struct test_settings), + SETTING_DEFINE_STRUCT_SIZE("size", size, struct test_settings), + SETTING_DEFINE_STRUCT_IN_PORT("port", port, struct test_settings), + SETTING_DEFINE_STRUCT_STR("str", str, struct test_settings), + { .type = SET_STR_VARS, .key = "expand_str", + offsetof(struct test_settings, expand_str), NULL }, + { .type = SET_STRLIST, .key = "strlist", + offsetof(struct test_settings, strlist), NULL }, + SETTING_DEFINE_LIST_END + }; + const struct setting_parser_info root = { + .module_name = "test", + .defines = defs, + .defaults = &test_defaults, + + .type_offset = SIZE_MAX, + .struct_size = sizeof(struct test_settings), + + .parent_offset = SIZE_MAX, + }; + + test_begin("settings_parser_get"); + + pool_t pool = pool_alloconly_create("settings parser", 1024); + struct setting_parser_context *ctx = + settings_parser_init(pool, &root, 0); + struct istream *is = test_istream_create(test_settings_blobs[0]); + const char *error = NULL; + int ret; + while((ret = settings_parse_stream_read(ctx, is)) > 0); + test_assert(ret == 0); + if (ret < 0) + i_error("settings_parse_stream failed: %s", + settings_parser_get_error(ctx)); + i_stream_unref(&is); + test_assert(settings_parser_check(ctx, pool, NULL)); + + /* check what we got */ + struct test_settings *settings = settings_parser_get(ctx); + test_assert(settings != NULL); + + test_assert(settings->bool_true == TRUE); + test_assert(settings->bool_false == FALSE); + test_assert(settings->uint == 15); + test_assert(settings->uint_oct == 0700); + test_assert(settings->secs == 5); + test_assert(settings->msecs == 5); + test_assert(settings->size == 1024); + test_assert(settings->port == 2205); + test_assert_strcmp(settings->str, "test string"); + test_assert_strcmp(settings->expand_str, "0test %{string}"); + + test_assert(array_count(&settings->strlist) == 6); + test_assert_strcmp(t_array_const_string_join(&settings->strlist, ";"), + "x;a;y;b;z;c"); + + const struct var_expand_table table[] = { + {'\0', "value", "string"}, + {'\0', NULL, NULL} + }; + + /* expand settings */ + test_assert(settings_var_expand(&root, settings, pool, table, &error) == 1 && + error == NULL); + + /* check that the setting got expanded */ + test_assert_strcmp(settings->expand_str, "test value"); + + settings_parser_deinit(&ctx); + pool_unref(&pool); + test_end(); +} + +int main(void) +{ + static void (*const test_functions[])(void) = { + test_settings_get_time, + test_settings_get_size, + test_settings_parser_get, + NULL + }; + return test_run(test_functions); +} |