From 367c3c77fc7cf993f99dda83cfd97a8dca3a2b7c Mon Sep 17 00:00:00 2001 From: Stephan Bosch Date: Tue, 6 Feb 2018 15:50:19 +0100 Subject: [PATCH] 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. --- src/lib/test-time-util.c | 138 +++++++++++++++++++++++++++++++++++++++ src/lib/time-util.c | 35 +++++++--- 2 files changed, 163 insertions(+), 10 deletions(-) diff --git a/src/lib/test-time-util.c b/src/lib/test-time-util.c index eff77bdddb..e0c7a29f61 100644 --- a/src/lib/test-time-util.c +++ b/src/lib/test-time-util.c @@ -54,6 +54,143 @@ static void test_timeval_cmp(void) 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 @@ static void test_strftime_fixed(void) void test_time_util(void) { test_timeval_cmp(); + test_timeval_cmp_margin(); test_timeval_diff(); test_time_to_local_day_start(); test_strftime_now(); diff --git a/src/lib/time-util.c b/src/lib/time-util.c index c38ab50f94..31eaf71b2e 100644 --- a/src/lib/time-util.c +++ b/src/lib/time-util.c @@ -23,16 +23,31 @@ int timeval_cmp(const struct timeval *tv1, const struct timeval *tv2) 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; - - 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; + unsigned long long usecs_diff; + int sec_margin, ret; + + 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)