1 | /* Tests for computing deadlines for timeouts. |
2 | Copyright (C) 2017-2024 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <inet/net-internal.h> |
20 | #include <limits.h> |
21 | #include <stdbool.h> |
22 | #include <stdint.h> |
23 | #include <support/check.h> |
24 | |
25 | /* Find the maximum value which can be represented in a time_t. */ |
26 | static time_t |
27 | time_t_max (void) |
28 | { |
29 | _Static_assert (0 > (time_t) -1, "time_t is signed" ); |
30 | uintmax_t current = 1; |
31 | while (true) |
32 | { |
33 | uintmax_t next = current * 2; |
34 | /* This cannot happen because time_t is signed. */ |
35 | TEST_VERIFY_EXIT (next > current); |
36 | ++next; |
37 | if ((time_t) next < 0 || next != (uintmax_t) (time_t) next) |
38 | /* Value cannot be represented in time_t. Return the previous |
39 | value. */ |
40 | return current; |
41 | current = next; |
42 | } |
43 | } |
44 | |
45 | static int |
46 | do_test (void) |
47 | { |
48 | { |
49 | struct deadline_current_time current_time = __deadline_current_time (); |
50 | TEST_VERIFY (current_time.current.tv_sec >= 0); |
51 | current_time = __deadline_current_time (); |
52 | /* Due to CLOCK_MONOTONIC, either seconds or nanoseconds are |
53 | greater than zero. This is also true for the gettimeofday |
54 | fallback. */ |
55 | TEST_VERIFY (current_time.current.tv_sec >= 0); |
56 | TEST_VERIFY (current_time.current.tv_sec > 0 |
57 | || current_time.current.tv_nsec > 0); |
58 | } |
59 | |
60 | /* Check basic computations of deadlines. */ |
61 | struct deadline_current_time current_time = { { 1, 123456789 } }; |
62 | struct deadline deadline = __deadline_from_timeval |
63 | (current_time, tv: (struct timeval) { 0, 1 }); |
64 | TEST_VERIFY (deadline.absolute.tv_sec == 1); |
65 | TEST_VERIFY (deadline.absolute.tv_nsec == 123457789); |
66 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1); |
67 | |
68 | deadline = __deadline_from_timeval |
69 | (current_time, tv: ((struct timeval) { 0, 2 })); |
70 | TEST_VERIFY (deadline.absolute.tv_sec == 1); |
71 | TEST_VERIFY (deadline.absolute.tv_nsec == 123458789); |
72 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1); |
73 | |
74 | deadline = __deadline_from_timeval |
75 | (current_time, tv: ((struct timeval) { 1, 0 })); |
76 | TEST_VERIFY (deadline.absolute.tv_sec == 2); |
77 | TEST_VERIFY (deadline.absolute.tv_nsec == 123456789); |
78 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000); |
79 | |
80 | /* Check if timeouts are correctly rounded up to the next |
81 | millisecond. */ |
82 | for (int i = 0; i < 999999; ++i) |
83 | { |
84 | ++current_time.current.tv_nsec; |
85 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000); |
86 | } |
87 | |
88 | /* A full millisecond has elapsed, so the time to the deadline is |
89 | now less than 1000. */ |
90 | ++current_time.current.tv_nsec; |
91 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 999); |
92 | |
93 | /* Check __deadline_to_ms carry-over. */ |
94 | current_time = (struct deadline_current_time) { { 9, 123456789 } }; |
95 | deadline = (struct deadline) { { 10, 122456789 } }; |
96 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 999); |
97 | deadline = (struct deadline) { { 10, 122456790 } }; |
98 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000); |
99 | deadline = (struct deadline) { { 10, 123456788 } }; |
100 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000); |
101 | deadline = (struct deadline) { { 10, 123456789 } }; |
102 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 1000); |
103 | |
104 | /* Check __deadline_to_ms overflow. */ |
105 | deadline = (struct deadline) { { INT_MAX - 1, 1 } }; |
106 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == INT_MAX); |
107 | |
108 | /* Check __deadline_to_ms for elapsed deadlines. */ |
109 | current_time = (struct deadline_current_time) { { 9, 123456789 } }; |
110 | deadline.absolute = current_time.current; |
111 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0); |
112 | current_time = (struct deadline_current_time) { { 9, 123456790 } }; |
113 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0); |
114 | current_time = (struct deadline_current_time) { { 10, 0 } }; |
115 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0); |
116 | current_time = (struct deadline_current_time) { { 10, 123456788 } }; |
117 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0); |
118 | current_time = (struct deadline_current_time) { { 10, 123456789 } }; |
119 | TEST_VERIFY (__deadline_to_ms (current_time, deadline) == 0); |
120 | |
121 | /* Check carry-over in __deadline_from_timeval. */ |
122 | current_time = (struct deadline_current_time) { { 9, 998000001 } }; |
123 | for (int i = 0; i < 2000; ++i) |
124 | { |
125 | deadline = __deadline_from_timeval |
126 | (current_time, tv: (struct timeval) { 1, i }); |
127 | TEST_VERIFY (deadline.absolute.tv_sec == 10); |
128 | TEST_VERIFY (deadline.absolute.tv_nsec == 998000001 + i * 1000); |
129 | } |
130 | for (int i = 2000; i < 3000; ++i) |
131 | { |
132 | deadline = __deadline_from_timeval |
133 | (current_time, tv: (struct timeval) { 2, i }); |
134 | TEST_VERIFY (deadline.absolute.tv_sec == 12); |
135 | TEST_VERIFY (deadline.absolute.tv_nsec == 1 + (i - 2000) * 1000); |
136 | } |
137 | |
138 | /* Check infinite deadlines. */ |
139 | deadline = __deadline_from_timeval |
140 | ((struct deadline_current_time) { { 0, 1000 * 1000 * 1000 - 1000 } }, |
141 | tv: (struct timeval) { time_t_max (), 1 }); |
142 | TEST_VERIFY (__deadline_is_infinite (deadline)); |
143 | deadline = __deadline_from_timeval |
144 | ((struct deadline_current_time) { { 0, 1000 * 1000 * 1000 - 1001 } }, |
145 | tv: (struct timeval) { time_t_max (), 1 }); |
146 | TEST_VERIFY (!__deadline_is_infinite (deadline)); |
147 | deadline = __deadline_from_timeval |
148 | ((struct deadline_current_time) |
149 | { { time_t_max (), 1000 * 1000 * 1000 - 1000 } }, |
150 | tv: (struct timeval) { 0, 1 }); |
151 | TEST_VERIFY (__deadline_is_infinite (deadline)); |
152 | deadline = __deadline_from_timeval |
153 | ((struct deadline_current_time) |
154 | { { time_t_max () / 2 + 1, 0 } }, |
155 | tv: (struct timeval) { time_t_max () / 2 + 1, 0 }); |
156 | TEST_VERIFY (__deadline_is_infinite (deadline)); |
157 | |
158 | /* Check __deadline_first behavior. */ |
159 | deadline = __deadline_first |
160 | (left: (struct deadline) { { 1, 2 } }, |
161 | right: (struct deadline) { { 1, 3 } }); |
162 | TEST_VERIFY (deadline.absolute.tv_sec == 1); |
163 | TEST_VERIFY (deadline.absolute.tv_nsec == 2); |
164 | deadline = __deadline_first |
165 | (left: (struct deadline) { { 1, 3 } }, |
166 | right: (struct deadline) { { 1, 2 } }); |
167 | TEST_VERIFY (deadline.absolute.tv_sec == 1); |
168 | TEST_VERIFY (deadline.absolute.tv_nsec == 2); |
169 | deadline = __deadline_first |
170 | (left: (struct deadline) { { 1, 2 } }, |
171 | right: (struct deadline) { { 2, 1 } }); |
172 | TEST_VERIFY (deadline.absolute.tv_sec == 1); |
173 | TEST_VERIFY (deadline.absolute.tv_nsec == 2); |
174 | deadline = __deadline_first |
175 | (left: (struct deadline) { { 1, 2 } }, |
176 | right: (struct deadline) { { 2, 4 } }); |
177 | TEST_VERIFY (deadline.absolute.tv_sec == 1); |
178 | TEST_VERIFY (deadline.absolute.tv_nsec == 2); |
179 | deadline = __deadline_first |
180 | (left: (struct deadline) { { 2, 4 } }, |
181 | right: (struct deadline) { { 1, 2 } }); |
182 | TEST_VERIFY (deadline.absolute.tv_sec == 1); |
183 | TEST_VERIFY (deadline.absolute.tv_nsec == 2); |
184 | |
185 | return 0; |
186 | } |
187 | |
188 | #include <support/test-driver.c> |
189 | |