1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 /* Test of gpr time support. */
20
21 #include <grpc/support/log.h>
22 #include <grpc/support/sync.h>
23 #include <grpc/support/time.h>
24 #include <inttypes.h>
25 #include <limits.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "test/core/util/test_config.h"
31
to_fp(void * arg,const char * buf,size_t len)32 static void to_fp(void* arg, const char* buf, size_t len) {
33 fwrite(buf, 1, len, static_cast<FILE*>(arg));
34 }
35
36 /* Convert gpr_intmax x to ascii base b (2..16), and write with
37 (*writer)(arg, ...), zero padding to "chars" digits). */
i_to_s(intmax_t x,int base,int chars,void (* writer)(void * arg,const char * buf,size_t len),void * arg)38 static void i_to_s(intmax_t x, int base, int chars,
39 void (*writer)(void* arg, const char* buf, size_t len),
40 void* arg) {
41 char buf[64];
42 char fmt[32];
43 GPR_ASSERT(base == 16 || base == 10);
44 sprintf(fmt, "%%0%d%s", chars, base == 16 ? PRIxMAX : PRIdMAX);
45 sprintf(buf, fmt, x);
46 (*writer)(arg, buf, strlen(buf));
47 }
48
49 /* Convert ts to ascii, and write with (*writer)(arg, ...). */
ts_to_s(gpr_timespec t,void (* writer)(void * arg,const char * buf,size_t len),void * arg)50 static void ts_to_s(gpr_timespec t,
51 void (*writer)(void* arg, const char* buf, size_t len),
52 void* arg) {
53 if (t.tv_sec < 0 && t.tv_nsec != 0) {
54 t.tv_sec++;
55 t.tv_nsec = GPR_NS_PER_SEC - t.tv_nsec;
56 }
57 i_to_s(t.tv_sec, 10, 0, writer, arg);
58 (*writer)(arg, ".", 1);
59 i_to_s(t.tv_nsec, 10, 9, writer, arg);
60 }
61
test_values(void)62 static void test_values(void) {
63 int i;
64
65 gpr_timespec x = gpr_time_0(GPR_CLOCK_REALTIME);
66 GPR_ASSERT(x.tv_sec == 0 && x.tv_nsec == 0);
67
68 x = gpr_inf_future(GPR_CLOCK_REALTIME);
69 fprintf(stderr, "far future ");
70 fflush(stderr);
71 i_to_s(x.tv_sec, 16, 16, &to_fp, stderr);
72 fprintf(stderr, "\n");
73 GPR_ASSERT(x.tv_sec == INT64_MAX);
74 fprintf(stderr, "far future ");
75 fflush(stderr);
76 ts_to_s(x, &to_fp, stderr);
77 fprintf(stderr, "\n");
78 fflush(stderr);
79
80 x = gpr_inf_past(GPR_CLOCK_REALTIME);
81 fprintf(stderr, "far past ");
82 fflush(stderr);
83 i_to_s(x.tv_sec, 16, 16, &to_fp, stderr);
84 fprintf(stderr, "\n");
85 fflush(stderr);
86 GPR_ASSERT(x.tv_sec == INT64_MIN);
87 fprintf(stderr, "far past ");
88 fflush(stderr);
89 ts_to_s(x, &to_fp, stderr);
90 fprintf(stderr, "\n");
91 fflush(stderr);
92
93 for (i = 1; i != 1000 * 1000 * 1000; i *= 10) {
94 x = gpr_time_from_micros(i, GPR_TIMESPAN);
95 GPR_ASSERT(x.tv_sec == i / GPR_US_PER_SEC &&
96 x.tv_nsec == (i % GPR_US_PER_SEC) * GPR_NS_PER_US);
97 x = gpr_time_from_nanos(i, GPR_TIMESPAN);
98 GPR_ASSERT(x.tv_sec == i / GPR_NS_PER_SEC &&
99 x.tv_nsec == (i % GPR_NS_PER_SEC));
100 x = gpr_time_from_millis(i, GPR_TIMESPAN);
101 GPR_ASSERT(x.tv_sec == i / GPR_MS_PER_SEC &&
102 x.tv_nsec == (i % GPR_MS_PER_SEC) * GPR_NS_PER_MS);
103 }
104
105 /* Test possible overflow in conversion of -ve values. */
106 x = gpr_time_from_micros(-(INT64_MAX - 999997), GPR_TIMESPAN);
107 GPR_ASSERT(x.tv_sec < 0);
108 GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC);
109
110 x = gpr_time_from_nanos(-(INT64_MAX - 999999997), GPR_TIMESPAN);
111 GPR_ASSERT(x.tv_sec < 0);
112 GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC);
113
114 x = gpr_time_from_millis(-(INT64_MAX - 997), GPR_TIMESPAN);
115 GPR_ASSERT(x.tv_sec < 0);
116 GPR_ASSERT(x.tv_nsec >= 0 && x.tv_nsec < GPR_NS_PER_SEC);
117
118 /* Test general -ve values. */
119 for (i = -1; i > -1000 * 1000 * 1000; i *= 7) {
120 x = gpr_time_from_micros(i, GPR_TIMESPAN);
121 GPR_ASSERT(x.tv_sec * GPR_US_PER_SEC + x.tv_nsec / GPR_NS_PER_US == i);
122 x = gpr_time_from_nanos(i, GPR_TIMESPAN);
123 GPR_ASSERT(x.tv_sec * GPR_NS_PER_SEC + x.tv_nsec == i);
124 x = gpr_time_from_millis(i, GPR_TIMESPAN);
125 GPR_ASSERT(x.tv_sec * GPR_MS_PER_SEC + x.tv_nsec / GPR_NS_PER_MS == i);
126 }
127 }
128
test_add_sub(void)129 static void test_add_sub(void) {
130 int i;
131 int j;
132 int k;
133 /* Basic addition and subtraction. */
134 for (i = -100; i <= 100; i++) {
135 for (j = -100; j <= 100; j++) {
136 for (k = 1; k <= 10000000; k *= 10) {
137 int sum = i + j;
138 int diff = i - j;
139 gpr_timespec it = gpr_time_from_micros(i * k, GPR_TIMESPAN);
140 gpr_timespec jt = gpr_time_from_micros(j * k, GPR_TIMESPAN);
141 gpr_timespec sumt = gpr_time_add(it, jt);
142 gpr_timespec difft = gpr_time_sub(it, jt);
143 if (gpr_time_cmp(gpr_time_from_micros(sum * k, GPR_TIMESPAN), sumt) !=
144 0) {
145 fprintf(stderr, "i %d j %d sum %d sumt ", i, j, sum);
146 fflush(stderr);
147 ts_to_s(sumt, &to_fp, stderr);
148 fprintf(stderr, "\n");
149 fflush(stderr);
150 GPR_ASSERT(0);
151 }
152 if (gpr_time_cmp(gpr_time_from_micros(diff * k, GPR_TIMESPAN), difft) !=
153 0) {
154 fprintf(stderr, "i %d j %d diff %d diff ", i, j, diff);
155 fflush(stderr);
156 ts_to_s(sumt, &to_fp, stderr);
157 fprintf(stderr, "\n");
158 fflush(stderr);
159 GPR_ASSERT(0);
160 }
161 }
162 }
163 }
164 }
165
test_overflow(void)166 static void test_overflow(void) {
167 /* overflow */
168 gpr_timespec x = gpr_time_from_micros(1, GPR_TIMESPAN);
169 do {
170 x = gpr_time_add(x, x);
171 } while (gpr_time_cmp(x, gpr_inf_future(GPR_TIMESPAN)) < 0);
172 GPR_ASSERT(gpr_time_cmp(x, gpr_inf_future(GPR_TIMESPAN)) == 0);
173 x = gpr_time_from_micros(-1, GPR_TIMESPAN);
174 do {
175 x = gpr_time_add(x, x);
176 } while (gpr_time_cmp(x, gpr_inf_past(GPR_TIMESPAN)) > 0);
177 GPR_ASSERT(gpr_time_cmp(x, gpr_inf_past(GPR_TIMESPAN)) == 0);
178 }
179
test_sticky_infinities(void)180 static void test_sticky_infinities(void) {
181 int i;
182 int j;
183 int k;
184 gpr_timespec infinity[2];
185 gpr_timespec addend[3];
186 infinity[0] = gpr_inf_future(GPR_TIMESPAN);
187 infinity[1] = gpr_inf_past(GPR_TIMESPAN);
188 addend[0] = gpr_inf_future(GPR_TIMESPAN);
189 addend[1] = gpr_inf_past(GPR_TIMESPAN);
190 addend[2] = gpr_time_0(GPR_TIMESPAN);
191
192 /* Infinities are sticky */
193 for (i = 0; i != sizeof(infinity) / sizeof(infinity[0]); i++) {
194 for (j = 0; j != sizeof(addend) / sizeof(addend[0]); j++) {
195 gpr_timespec x = gpr_time_add(infinity[i], addend[j]);
196 GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0);
197 x = gpr_time_sub(infinity[i], addend[j]);
198 GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0);
199 }
200 for (k = -200; k <= 200; k++) {
201 gpr_timespec y = gpr_time_from_micros(k * 100000, GPR_TIMESPAN);
202 gpr_timespec x = gpr_time_add(infinity[i], y);
203 GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0);
204 x = gpr_time_sub(infinity[i], y);
205 GPR_ASSERT(gpr_time_cmp(x, infinity[i]) == 0);
206 }
207 }
208 }
209
test_similar(void)210 static void test_similar(void) {
211 GPR_ASSERT(1 == gpr_time_similar(gpr_inf_future(GPR_TIMESPAN),
212 gpr_inf_future(GPR_TIMESPAN),
213 gpr_time_0(GPR_TIMESPAN)));
214 GPR_ASSERT(1 == gpr_time_similar(gpr_inf_past(GPR_TIMESPAN),
215 gpr_inf_past(GPR_TIMESPAN),
216 gpr_time_0(GPR_TIMESPAN)));
217 GPR_ASSERT(0 == gpr_time_similar(gpr_inf_past(GPR_TIMESPAN),
218 gpr_inf_future(GPR_TIMESPAN),
219 gpr_time_0(GPR_TIMESPAN)));
220 GPR_ASSERT(0 == gpr_time_similar(gpr_inf_future(GPR_TIMESPAN),
221 gpr_inf_past(GPR_TIMESPAN),
222 gpr_time_0(GPR_TIMESPAN)));
223 GPR_ASSERT(1 == gpr_time_similar(gpr_time_from_micros(10, GPR_TIMESPAN),
224 gpr_time_from_micros(10, GPR_TIMESPAN),
225 gpr_time_0(GPR_TIMESPAN)));
226 GPR_ASSERT(1 == gpr_time_similar(gpr_time_from_micros(10, GPR_TIMESPAN),
227 gpr_time_from_micros(15, GPR_TIMESPAN),
228 gpr_time_from_micros(10, GPR_TIMESPAN)));
229 GPR_ASSERT(1 == gpr_time_similar(gpr_time_from_micros(15, GPR_TIMESPAN),
230 gpr_time_from_micros(10, GPR_TIMESPAN),
231 gpr_time_from_micros(10, GPR_TIMESPAN)));
232 GPR_ASSERT(0 == gpr_time_similar(gpr_time_from_micros(10, GPR_TIMESPAN),
233 gpr_time_from_micros(25, GPR_TIMESPAN),
234 gpr_time_from_micros(10, GPR_TIMESPAN)));
235 GPR_ASSERT(0 == gpr_time_similar(gpr_time_from_micros(25, GPR_TIMESPAN),
236 gpr_time_from_micros(10, GPR_TIMESPAN),
237 gpr_time_from_micros(10, GPR_TIMESPAN)));
238 }
239
test_convert_extreme(void)240 static void test_convert_extreme(void) {
241 gpr_timespec realtime = {INT64_MAX, 1, GPR_CLOCK_REALTIME};
242 gpr_timespec monotime = gpr_convert_clock_type(realtime, GPR_CLOCK_MONOTONIC);
243 GPR_ASSERT(monotime.tv_sec == realtime.tv_sec);
244 GPR_ASSERT(monotime.clock_type == GPR_CLOCK_MONOTONIC);
245 }
246
test_cmp_extreme(void)247 static void test_cmp_extreme(void) {
248 gpr_timespec t1 = {INT64_MAX, 1, GPR_CLOCK_REALTIME};
249 gpr_timespec t2 = {INT64_MAX, 2, GPR_CLOCK_REALTIME};
250 GPR_ASSERT(gpr_time_cmp(t1, t2) == 0);
251 t1.tv_sec = INT64_MIN;
252 t2.tv_sec = INT64_MIN;
253 GPR_ASSERT(gpr_time_cmp(t1, t2) == 0);
254 }
255
main(int argc,char * argv[])256 int main(int argc, char* argv[]) {
257 grpc::testing::TestEnvironment env(argc, argv);
258
259 test_values();
260 test_add_sub();
261 test_overflow();
262 test_sticky_infinities();
263 test_similar();
264 test_convert_extreme();
265 test_cmp_extreme();
266 return 0;
267 }
268