glibc/inet/tst-deadline.c

189 lines
7.4 KiB
C

/* Tests for computing deadlines for timeouts.
Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <inet/net-internal.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <support/check.h>
/* Find the maximum value which can be represented in a time_t. */
static time_t
time_t_max (void)
{
_Static_assert (0 > (time_t) -1, "time_t is signed");
uintmax_t current = 1;
while (true)
{
uintmax_t next = current * 2;
/* This cannot happen because time_t is signed. */
TEST_VERIFY_EXIT (next > current);
++next;
if ((time_t) next < 0 || next != (uintmax_t) (time_t) next)
/* Value cannot be represented in time_t. Return the previous
value. */
return current;
current = next;
}
}
static int
do_test (void)
{
{
struct deadline_current_time current_time = __deadline_current_time ();
TEST_VERIFY (current_time.current.tv_sec >= 0);
current_time = __deadline_current_time ();
/* Due to CLOCK_MONOTONIC, either seconds or nanoseconds are
greater than zero. This is also true for the gettimeofday
fallback. */
TEST_VERIFY (current_time.current.tv_sec >= 0);
TEST_VERIFY (current_time.current.tv_sec > 0
|| current_time.current.tv_nsec > 0);
}
/* Check basic computations of deadlines. */
struct deadline_current_time current_time = { { 1, 123456789 } };
struct deadline deadline = __deadline_from_timeval
(current_time, (struct timeval) { 0, 1 });
TEST_VERIFY (deadline.absolute.tv_sec == 1);
TEST_VERIFY (deadline.absolute.tv_nsec == 123457789);
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1);
deadline = __deadline_from_timeval
(current_time, ((struct timeval) { 0, 2 }));
TEST_VERIFY (deadline.absolute.tv_sec == 1);
TEST_VERIFY (deadline.absolute.tv_nsec == 123458789);
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1);
deadline = __deadline_from_timeval
(current_time, ((struct timeval) { 1, 0 }));
TEST_VERIFY (deadline.absolute.tv_sec == 2);
TEST_VERIFY (deadline.absolute.tv_nsec == 123456789);
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000);
/* Check if timeouts are correctly rounded up to the next
millisecond. */
for (int i = 0; i < 999999; ++i)
{
++current_time.current.tv_nsec;
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000);
}
/* A full millisecond has elapsed, so the time to the deadline is
now less than 1000. */
++current_time.current.tv_nsec;
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 999);
/* Check __deadline_to_ms carry-over. */
current_time = (struct deadline_current_time) { { 9, 123456789 } };
deadline = (struct deadline) { { 10, 122456789 } };
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 999);
deadline = (struct deadline) { { 10, 122456790 } };
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000);
deadline = (struct deadline) { { 10, 123456788 } };
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000);
deadline = (struct deadline) { { 10, 123456789 } };
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000);
/* Check __deadline_to_ms overflow. */
deadline = (struct deadline) { { INT_MAX - 1, 1 } };
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == INT_MAX);
/* Check __deadline_to_ms for elapsed deadlines. */
current_time = (struct deadline_current_time) { { 9, 123456789 } };
deadline.absolute = current_time.current;
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0);
current_time = (struct deadline_current_time) { { 9, 123456790 } };
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0);
current_time = (struct deadline_current_time) { { 10, 0 } };
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0);
current_time = (struct deadline_current_time) { { 10, 123456788 } };
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0);
current_time = (struct deadline_current_time) { { 10, 123456789 } };
TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0);
/* Check carry-over in __deadline_from_timeval. */
current_time = (struct deadline_current_time) { { 9, 998000001 } };
for (int i = 0; i < 2000; ++i)
{
deadline = __deadline_from_timeval
(current_time, (struct timeval) { 1, i });
TEST_VERIFY (deadline.absolute.tv_sec == 10);
TEST_VERIFY (deadline.absolute.tv_nsec == 998000001 + i * 1000);
}
for (int i = 2000; i < 3000; ++i)
{
deadline = __deadline_from_timeval
(current_time, (struct timeval) { 2, i });
TEST_VERIFY (deadline.absolute.tv_sec == 12);
TEST_VERIFY (deadline.absolute.tv_nsec == 1 + (i - 2000) * 1000);
}
/* Check infinite deadlines. */
deadline = __deadline_from_timeval
((struct deadline_current_time) { { 0, 1000 * 1000 * 1000 - 1000 } },
(struct timeval) { time_t_max (), 1 });
TEST_VERIFY (__deadline_is_infinite (deadline));
deadline = __deadline_from_timeval
((struct deadline_current_time) { { 0, 1000 * 1000 * 1000 - 1001 } },
(struct timeval) { time_t_max (), 1 });
TEST_VERIFY (!__deadline_is_infinite (deadline));
deadline = __deadline_from_timeval
((struct deadline_current_time)
{ { time_t_max (), 1000 * 1000 * 1000 - 1000 } },
(struct timeval) { 0, 1 });
TEST_VERIFY (__deadline_is_infinite (deadline));
deadline = __deadline_from_timeval
((struct deadline_current_time)
{ { time_t_max () / 2 + 1, 0 } },
(struct timeval) { time_t_max () / 2 + 1, 0 });
TEST_VERIFY (__deadline_is_infinite (deadline));
/* Check __deadline_first behavior. */
deadline = __deadline_first
((struct deadline) { { 1, 2 } },
(struct deadline) { { 1, 3 } });
TEST_VERIFY (deadline.absolute.tv_sec == 1);
TEST_VERIFY (deadline.absolute.tv_nsec == 2);
deadline = __deadline_first
((struct deadline) { { 1, 3 } },
(struct deadline) { { 1, 2 } });
TEST_VERIFY (deadline.absolute.tv_sec == 1);
TEST_VERIFY (deadline.absolute.tv_nsec == 2);
deadline = __deadline_first
((struct deadline) { { 1, 2 } },
(struct deadline) { { 2, 1 } });
TEST_VERIFY (deadline.absolute.tv_sec == 1);
TEST_VERIFY (deadline.absolute.tv_nsec == 2);
deadline = __deadline_first
((struct deadline) { { 1, 2 } },
(struct deadline) { { 2, 4 } });
TEST_VERIFY (deadline.absolute.tv_sec == 1);
TEST_VERIFY (deadline.absolute.tv_nsec == 2);
deadline = __deadline_first
((struct deadline) { { 2, 4 } },
(struct deadline) { { 1, 2 } });
TEST_VERIFY (deadline.absolute.tv_sec == 1);
TEST_VERIFY (deadline.absolute.tv_nsec == 2);
return 0;
}
#include <support/test-driver.c>