time: make timemono a first-class citizen.
[ccan] / ccan / time / test / run-check.c
1 #define DEBUG
2 #include <ccan/time/time.h>
3 #include <ccan/time/time.c>
4 #include <ccan/tap/tap.h>
5 #include <unistd.h>
6 #include <stdlib.h>
7 #include <signal.h>
8 #include <sys/types.h>
9 #include <sys/wait.h>
10
11 /* If we really abort, we don't get coverage info! */
12 void abort(void)
13 {
14         exit(7);
15 }
16
17 int main(void)
18 {
19         struct timeabs t1, t2, epoch = { { 0, 0 } };
20         struct timemono t1m, t2m;
21         struct timerel t3, t4, zero = { { 0, 0 } };
22         int fds[2];
23
24         plan_tests(69);
25
26         /* Test time_now */
27         t1 = time_now();
28         t2 = time_now();
29
30         /* Test time_between. */
31         t3 = time_between(t2, t1);
32         ok1(t3.ts.tv_sec > 0 || t3.ts.tv_nsec >= 0);
33         t3 = time_between(t2, t2);
34         ok1(t3.ts.tv_sec == 0 && t3.ts.tv_nsec == 0);
35         t3 = time_between(t1, t1);
36         ok1(t3.ts.tv_sec == 0 && t3.ts.tv_nsec == 0);
37
38         /* Test timeabs_eq / timerel_eq */
39         ok1(timeabs_eq(t1, t1));
40         ok1(timeabs_eq(t2, t2));
41         ok1(!timeabs_eq(t1, epoch));
42         ok1(!timeabs_eq(t2, epoch));
43         t3.ts.tv_sec = 1;
44         ok1(timerel_eq(t3, t3));
45         ok1(!timerel_eq(t3, zero));
46
47         /* Test time_mono */
48         t1m = time_mono();
49         t2m = time_mono();
50
51         ok1(!time_less_(t2m.ts, t1m.ts));
52
53         t3.ts.tv_sec = 1;
54         t3.ts.tv_nsec = 0;
55
56         ok1(time_less(timemono_between(t2m, t1m), t3));
57         ok1(time_less(timemono_since(t1m), t3));
58
59         ok1(timemono_add(t1m, t3).ts.tv_sec == t1m.ts.tv_sec + 1);
60         ok1(timemono_add(t2m, t3).ts.tv_nsec == t2m.ts.tv_nsec);
61
62         /* Make sure t2 > t1. */
63         t3.ts.tv_sec = 0;
64         t3.ts.tv_nsec = 1;
65         t2 = timeabs_add(t2, t3);
66
67         /* Test time_before and time_after. */
68         ok1(!timeabs_eq(t1, t2));
69         ok1(!time_after(t1, t2));
70         ok1(time_before(t1, t2));
71         ok1(time_after(t2, t1));
72         ok1(!time_before(t2, t1));
73         t3.ts.tv_sec = 0;
74         t3.ts.tv_nsec = 999999999;
75         t2 = timeabs_add(t2, t3);
76         ok1(!timeabs_eq(t1, t2));
77         ok1(!time_after(t1, t2));
78         ok1(time_before(t1, t2));
79         ok1(time_after(t2, t1));
80         ok1(!time_before(t2, t1));
81
82         t3 = time_between(t2, epoch);
83         ok1(t2.ts.tv_sec == t3.ts.tv_sec && t2.ts.tv_nsec == t3.ts.tv_nsec);
84         t3 = time_between(t2, t2);
85         ok1(timerel_eq(t3, zero));
86
87         /* time_from_msec / time_to_msec */
88         t3 = time_from_msec(500);
89         ok1(t3.ts.tv_sec == 0);
90         ok1(t3.ts.tv_nsec == 500000000);
91         ok1(time_to_msec(t3) == 500);
92
93         t3 = time_from_msec(1000);
94         ok1(t3.ts.tv_sec == 1);
95         ok1(t3.ts.tv_nsec == 0);
96         ok1(time_to_msec(t3) == 1000);
97
98         t3 = time_from_msec(1500);
99         ok1(t3.ts.tv_sec == 1);
100         ok1(t3.ts.tv_nsec == 500000000);
101         ok1(time_to_msec(t3) == 1500);
102
103         /* time_from_usec */
104         t3 = time_from_usec(500000);
105         ok1(t3.ts.tv_sec == 0);
106         ok1(t3.ts.tv_nsec == 500000000);
107         ok1(time_to_usec(t3) == 500000);
108
109         t3 = time_from_usec(1000000);
110         ok1(t3.ts.tv_sec == 1);
111         ok1(t3.ts.tv_nsec == 0);
112         ok1(time_to_usec(t3) == 1000000);
113
114         t3 = time_from_usec(1500000);
115         ok1(t3.ts.tv_sec == 1);
116         ok1(t3.ts.tv_nsec == 500000000);
117         ok1(time_to_usec(t3) == 1500000);
118
119         /* time_from_nsec */
120         t3 = time_from_nsec(500000000);
121         ok1(t3.ts.tv_sec == 0);
122         ok1(t3.ts.tv_nsec == 500000000);
123         ok1(time_to_nsec(t3) == 500000000);
124
125         t3 = time_from_nsec(1000000000);
126         ok1(t3.ts.tv_sec == 1);
127         ok1(t3.ts.tv_nsec == 0);
128         ok1(time_to_nsec(t3) == 1000000000);
129
130         t3 = time_from_nsec(1500000000);
131         ok1(t3.ts.tv_sec == 1);
132         ok1(t3.ts.tv_nsec == 500000000);
133         ok1(time_to_nsec(t3) == 1500000000);
134
135         /* Test wrapunder */
136         t1 = timeabs_sub(timeabs_sub(t2, time_from_msec(500)),
137                          time_from_msec(500));
138         ok1(t1.ts.tv_sec == t2.ts.tv_sec - 1);
139         ok1(t1.ts.tv_nsec == t2.ts.tv_nsec);
140
141         /* time_divide and time_multiply */
142         t4.ts.tv_nsec = 100;
143         t4.ts.tv_sec = 100;
144
145         t3 = time_divide(t4, 2);
146         ok1(t3.ts.tv_sec == 50);
147         ok1(t3.ts.tv_nsec == 50);
148
149         t3 = time_divide(t4, 100);
150         ok1(t3.ts.tv_sec == 1);
151         ok1(t3.ts.tv_nsec == 1);
152
153         t3 = time_multiply(t3, 100);
154         ok1(timerel_eq(t3, t4));
155
156         t3 = time_divide(t4, 200);
157         ok1(t3.ts.tv_sec == 0);
158         ok1(t3.ts.tv_nsec == 500000000);
159
160         /* Divide by huge number. */
161         t4.ts.tv_sec = (1U << 31) - 1;
162         t4.ts.tv_nsec = 999999999;
163         t3 = time_divide(t4, 1 << 30);
164         /* Allow us to round either way. */
165         ok1((t3.ts.tv_sec == 2 && t3.ts.tv_nsec == 0)
166             || (t3.ts.tv_sec == 1 && t3.ts.tv_nsec == 999999999));
167
168         /* Multiply by huge number. */
169         t4.ts.tv_sec = 0;
170         t4.ts.tv_nsec = 1;
171         t3 = time_multiply(t4, 1UL << 31);
172         ok1(t3.ts.tv_sec == 2);
173         ok1(t3.ts.tv_nsec == 147483648);
174
175         if (pipe(fds) != 0)
176                 exit(1);
177
178         fflush(stdout);
179         switch (fork()) {
180         case 0:
181                 close(fds[0]);
182                 dup2(fds[1], 1);
183                 dup2(fds[1], 2);
184                 t1.ts.tv_sec = 7;
185                 t1.ts.tv_nsec = 1000000001;
186                 t2 = timeabs_check(t1, NULL);
187                 if (t2.ts.tv_sec != 8 || t2.ts.tv_nsec != 1)
188                         exit(1);
189                 t1.ts.tv_sec = -1;
190                 t1.ts.tv_nsec = 5;
191                 t2 = timeabs_check(t1, NULL);
192                 if (t2.ts.tv_sec != 0 || t2.ts.tv_nsec != 5)
193                         exit(1);
194                 t1.ts.tv_sec = 8;
195                 t1.ts.tv_nsec = 1000000002;
196                 /* We expect this to abort! */
197                 t2 = timeabs_check(t1, "abortstr");
198                 exit(1);
199                 
200         default: {
201                 char readbuf[1024];
202                 int r, len = 0;
203
204                 close(fds[1]);
205                 while ((r = read(fds[0], readbuf + len, 1023 - len)) > 0)
206                         len += r;
207                 readbuf[len] = '\0';
208                 ok1(strcmp(readbuf,
209                            "WARNING: malformed time"
210                            " 7 seconds 1000000001 ns converted to 8.000000001.\n"
211                            "WARNING: malformed time"
212                            " -1 seconds 5 ns converted to 0.000000005.\n"
213                            "abortstr: malformed time 8.1000000002\n") == 0);
214                 ok1(wait(&r) != -1);
215                 ok1(WIFEXITED(r));
216                 ok1(WEXITSTATUS(r) == 7);
217         }
218         }
219
220         return exit_status();
221 }