Mercurial > dovecot > core-2.2
changeset 21387:5241d95f5872
lib-settings: Added settings_get_time_msecs()
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Fri, 06 May 2016 21:43:04 +0300 |
parents | aac8169ef34d |
children | a8fc5f34b8fa |
files | src/lib-settings/Makefile.am src/lib-settings/settings-parser.c src/lib-settings/settings-parser.h src/lib-settings/test-settings-parser.c |
diffstat | 4 files changed, 211 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-settings/Makefile.am Tue Jan 10 14:45:20 2017 +0200 +++ b/src/lib-settings/Makefile.am Fri May 06 21:43:04 2016 +0300 @@ -1,7 +1,8 @@ noinst_LTLIBRARIES = libsettings.la AM_CPPFLAGS = \ - -I$(top_srcdir)/src/lib + -I$(top_srcdir)/src/lib \ + -I$(top_srcdir)/src/lib-test libsettings_la_SOURCES = \ settings.c \ @@ -13,3 +14,23 @@ pkginc_libdir=$(pkgincludedir) pkginc_lib_HEADERS = $(headers) + +test_programs = \ + test-settings-parser + +noinst_PROGRAMS = $(test_programs) + +test_libs = \ + libsettings.la \ + ../lib-test/libtest.la \ + ../lib/liblib.la + +test_settings_parser_SOURCES = test-settings-parser.c +test_settings_parser_LDADD = $(test_libs) +test_settings_parser_DEPENDENCIES = $(test_libs) + +check: check-am check-test +check-test: all-am + for bin in $(test_programs); do \ + if ! $(RUN_TEST) ./$$bin; then exit 1; fi; \ + done
--- a/src/lib-settings/settings-parser.c Tue Jan 10 14:45:20 2017 +0200 +++ b/src/lib-settings/settings-parser.c Fri May 06 21:43:04 2016 +0300 @@ -347,10 +347,10 @@ return 0; } -int settings_get_time(const char *str, unsigned int *secs_r, - const char **error_r) +static int settings_get_time_full(const char *str, unsigned int *interval_r, + bool milliseconds, const char **error_r) { - uintmax_t num, multiply = 1; + uintmax_t num, multiply = milliseconds ? 1000 : 1; const char *p; if (str_parse_uintmax(str, &num, &p) < 0) { @@ -360,29 +360,47 @@ while (*p == ' ') p++; switch (i_toupper(*p)) { case 'S': - multiply = 1; + multiply *= 1; if (strncasecmp(p, "secs", strlen(p)) == 0 || strncasecmp(p, "seconds", strlen(p)) == 0) p = ""; break; case 'M': - multiply = 60; + multiply *= 60; if (strncasecmp(p, "mins", strlen(p)) == 0 || strncasecmp(p, "minutes", strlen(p)) == 0) p = ""; + else if (strncasecmp(p, "msecs", strlen(p)) == 0 || + strncasecmp(p, "mseconds", strlen(p)) == 0 || + strncasecmp(p, "millisecs", strlen(p)) == 0 || + strncasecmp(p, "milliseconds", strlen(p)) == 0) { + if (milliseconds || (num % 1000) == 0) { + if (!milliseconds) { + /* allow ms also for seconds, as long + as it's divisible by seconds */ + num /= 1000; + } + multiply = 1; + p = ""; + break; + } + *error_r = t_strdup_printf( + "Milliseconds not supported for this setting: %s", str); + return -1; + } break; case 'H': - multiply = 60*60; + multiply *= 60*60; if (strncasecmp(p, "hours", strlen(p)) == 0) p = ""; break; case 'D': - multiply = 60*60*24; + multiply *= 60*60*24; if (strncasecmp(p, "days", strlen(p)) == 0) p = ""; break; case 'W': - multiply = 60*60*24*7; + multiply *= 60*60*24*7; if (strncasecmp(p, "weeks", strlen(p)) == 0) p = ""; break; @@ -397,10 +415,22 @@ str, NULL); return -1; } - *secs_r = num * multiply; + *interval_r = num * multiply; return 0; } +int settings_get_time(const char *str, unsigned int *secs_r, + const char **error_r) +{ + return settings_get_time_full(str, secs_r, FALSE, error_r); +} + +int settings_get_time_msecs(const char *str, unsigned int *msecs_r, + const char **error_r) +{ + return settings_get_time_full(str, msecs_r, TRUE, error_r); +} + int settings_get_size(const char *str, uoff_t *bytes_r, const char **error_r) {
--- a/src/lib-settings/settings-parser.h Tue Jan 10 14:45:20 2017 +0200 +++ b/src/lib-settings/settings-parser.h Fri May 06 21:43:04 2016 +0300 @@ -240,6 +240,9 @@ /* Parse time interval string, return as seconds. */ int settings_get_time(const char *str, unsigned int *secs_r, const char **error_r); +/* Parse time interval string, return as milliseconds. */ +int settings_get_time_msecs(const char *str, unsigned int *msecs_r, + const char **error_r); /* Parse size string, return as bytes. */ int settings_get_size(const char *str, uoff_t *bytes_r, const char **error_r);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-settings/test-settings-parser.c Fri May 06 21:43:04 2016 +0300 @@ -0,0 +1,147 @@ +/* Copyright (c) 2009-2016 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "settings-parser.h" +#include "test-common.h" + +static void test_settings_get_time(void) +{ + 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", + /* 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", + /* 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(); +} + +int main(void) +{ + static void (*test_functions[])(void) = { + test_settings_get_time, + NULL + }; + return test_run(test_functions); +}