Mercurial > dovecot > core-2.2
changeset 22804:33a2b955ea19
lib: time-util: Fix timeval_cmp_margin() to correctly handle a margin crossing the second boundary.
The timeval_cmp_margin() function incorrectly assumed that the margin is
irrelevent when the tv_sec values are different.
author | Stephan Bosch <stephan.bosch@dovecot.fi> |
---|---|
date | Tue, 06 Feb 2018 15:50:19 +0100 |
parents | 766e2da35883 |
children | dbb45b0865be |
files | src/lib/test-time-util.c src/lib/time-util.c |
diffstat | 2 files changed, 162 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/test-time-util.c Tue Feb 06 16:51:23 2018 +0100 +++ b/src/lib/test-time-util.c Tue Feb 06 15:50:19 2018 +0100 @@ -54,6 +54,143 @@ test_end(); } +static void test_timeval_cmp_margin(void) +{ + static const struct { + struct timeval tv1, tv2; + unsigned int margin; + int output; + } tests[] = { + { + .tv1 = { 0, 0 }, + .tv2 = { 0, 0 }, + .output = 0, + },{ + .tv1 = { INT_MAX, 999999 }, + .tv2 = { INT_MAX, 999999 }, + .output = 0, + + },{ + .tv1 = { 0, 0 }, + .tv2 = { 0, 1 }, + .output = -1, + },{ + .tv1 = { 0, 0 }, + .tv2 = { 1, 0 }, + .output = -1, + },{ + .tv1 = { 0, 999999 }, + .tv2 = { 1, 0 }, + .output = -1, + },{ + .tv1 = { 1, 0 }, + .tv2 = { 1, 1 }, + .output = -1, + },{ + .tv1 = { -INT_MAX, 0 }, + .tv2 = { INT_MAX, 0 }, + .output = -1, + },{ + .tv1 = { 0, 999999 }, + .tv2 = { 1, 0 }, + .margin = 1, + .output = 0, + },{ + .tv1 = { 1, 0 }, + .tv2 = { 1, 1 }, + .margin = 1, + .output = 0, + },{ + .tv1 = { 0, 999998 }, + .tv2 = { 1, 0 }, + .margin = 1, + .output = -1, + },{ + .tv1 = { 1, 0 }, + .tv2 = { 1, 2 }, + .margin = 1, + .output = -1, + },{ + .tv1 = { 0, 998000 }, + .tv2 = { 1, 0 }, + .margin = 2000, + .output = 0, + },{ + .tv1 = { 1, 0 }, + .tv2 = { 1, 2000 }, + .margin = 2000, + .output = 0, + },{ + .tv1 = { 0, 997999 }, + .tv2 = { 1, 0 }, + .margin = 2000, + .output = -1, + },{ + .tv1 = { 1, 0 }, + .tv2 = { 1, 2001 }, + .margin = 2000, + .output = -1, + },{ + .tv1 = { 0, 1 }, + .tv2 = { 1, 0 }, + .margin = 999999, + .output = 0, + },{ + .tv1 = { 1, 0 }, + .tv2 = { 1, 999999 }, + .margin = 999999, + .output = 0, + },{ + .tv1 = { 0, 0 }, + .tv2 = { 1, 0 }, + .margin = 999999, + .output = -1, + },{ + .tv1 = { 1, 0 }, + .tv2 = { 2, 0 }, + .margin = 999999, + .output = -1, + },{ + .tv1 = { 10, 0 }, + .tv2 = { 11, 500000 }, + .margin = 1500000, + .output = 0, + },{ + .tv1 = { 8, 500000 }, + .tv2 = { 10, 0 }, + .margin = 1500000, + .output = 0, + },{ + .tv1 = { 10, 0 }, + .tv2 = { 11, 500001 }, + .margin = 1500000, + .output = -1, + },{ + .tv1 = { 8, 499999 }, + .tv2 = { 10, 0 }, + .margin = 1500000, + .output = -1, + },{ + .tv1 = { 1517925358, 999989 }, + .tv2 = { 1517925359, 753 }, + .margin = 2000, + .output = 0, + } + }; + unsigned int i; + + test_begin("timeval_cmp_margin()"); + for (i = 0; i < N_ELEMENTS(tests); i++) { + const struct timeval *tv1 = &tests[i].tv1, *tv2 = &tests[i].tv2; + unsigned int margin = tests[i].margin; + int output = tests[i].output; + + test_assert(timeval_cmp_margin(tv1, tv2, margin) == output); + test_assert(timeval_cmp_margin(tv2, tv1, margin) == -output); + } + test_end(); +} + static void test_timeval_diff(void) { static struct timeval input[] = { @@ -201,6 +338,7 @@ void test_time_util(void) { test_timeval_cmp(); + test_timeval_cmp_margin(); test_timeval_diff(); test_time_to_local_day_start(); test_strftime_now();
--- a/src/lib/time-util.c Tue Feb 06 16:51:23 2018 +0100 +++ b/src/lib/time-util.c Tue Feb 06 15:50:19 2018 +0100 @@ -23,16 +23,31 @@ int timeval_cmp_margin(const struct timeval *tv1, const struct timeval *tv2, unsigned int usec_margin) { - if (tv1->tv_sec < tv2->tv_sec) - return -1; - if (tv1->tv_sec > tv2->tv_sec) - return 1; + unsigned long long usecs_diff; + int sec_margin, ret; - if ((tv2->tv_usec - tv1->tv_usec) > (int)usec_margin) - return -1; - if ((tv1->tv_usec - tv2->tv_usec) > (int)usec_margin) - return 1; - return 0; + if (tv1->tv_sec < tv2->tv_sec) { + sec_margin = ((int)usec_margin / 1000000) + 1; + if ((tv2->tv_sec - tv1->tv_sec) > sec_margin) + return -1; + usecs_diff = (tv2->tv_sec - tv1->tv_sec) * 1000000ULL + + (tv2->tv_usec - tv1->tv_usec); + ret = -1; + } else if (tv1->tv_sec > tv2->tv_sec) { + sec_margin = ((int)usec_margin / 1000000) + 1; + if ((tv1->tv_sec - tv2->tv_sec) > sec_margin) + return 1; + usecs_diff = (tv1->tv_sec - tv2->tv_sec) * 1000000ULL + + (tv1->tv_usec - tv2->tv_usec); + ret = 1; + } else if (tv1->tv_usec < tv2->tv_usec) { + usecs_diff = tv2->tv_usec - tv1->tv_usec; + ret = -1; + } else { + usecs_diff = tv1->tv_usec - tv2->tv_usec; + ret = 1; + } + return usecs_diff > usec_margin ? ret : 0; } int timeval_diff_msecs(const struct timeval *tv1, const struct timeval *tv2)