time: split absolute and relative times.
[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 timerel t3, t4, zero = { { 0, 0 } };
21         int fds[2];
22
23         plan_tests(64);
24
25         /* Test time_now */
26         t1 = time_now();
27         t2 = time_now();
28
29         /* Test time_between. */
30         t3 = time_between(t2, t1);
31         ok1(t3.ts.tv_sec > 0 || t3.ts.tv_nsec >= 0);
32         t3 = time_between(t2, t2);
33         ok1(t3.ts.tv_sec == 0 && t3.ts.tv_nsec == 0);
34         t3 = time_between(t1, t1);
35         ok1(t3.ts.tv_sec == 0 && t3.ts.tv_nsec == 0);
36
37         /* Test timeabs_eq / timerel_eq */
38         ok1(timeabs_eq(t1, t1));
39         ok1(timeabs_eq(t2, t2));
40         ok1(!timeabs_eq(t1, epoch));
41         ok1(!timeabs_eq(t2, epoch));
42         t3.ts.tv_sec = 1;
43         ok1(timerel_eq(t3, t3));
44         ok1(!timerel_eq(t3, zero));
45
46         /* Make sure t2 > t1. */
47         t3.ts.tv_sec = 0;
48         t3.ts.tv_nsec = 1;
49         t2 = timeabs_add(t2, t3);
50
51         /* Test time_before and time_after. */
52         ok1(!timeabs_eq(t1, t2));
53         ok1(!time_after(t1, t2));
54         ok1(time_before(t1, t2));
55         ok1(time_after(t2, t1));
56         ok1(!time_before(t2, t1));
57         t3.ts.tv_sec = 0;
58         t3.ts.tv_nsec = 999999999;
59         t2 = timeabs_add(t2, t3);
60         ok1(!timeabs_eq(t1, t2));
61         ok1(!time_after(t1, t2));
62         ok1(time_before(t1, t2));
63         ok1(time_after(t2, t1));
64         ok1(!time_before(t2, t1));
65
66         t3 = time_between(t2, epoch);
67         ok1(t2.ts.tv_sec == t3.ts.tv_sec && t2.ts.tv_nsec == t3.ts.tv_nsec);
68         t3 = time_between(t2, t2);
69         ok1(timerel_eq(t3, zero));
70
71         /* time_from_msec / time_to_msec */
72         t3 = time_from_msec(500);
73         ok1(t3.ts.tv_sec == 0);
74         ok1(t3.ts.tv_nsec == 500000000);
75         ok1(time_to_msec(t3) == 500);
76
77         t3 = time_from_msec(1000);
78         ok1(t3.ts.tv_sec == 1);
79         ok1(t3.ts.tv_nsec == 0);
80         ok1(time_to_msec(t3) == 1000);
81
82         t3 = time_from_msec(1500);
83         ok1(t3.ts.tv_sec == 1);
84         ok1(t3.ts.tv_nsec == 500000000);
85         ok1(time_to_msec(t3) == 1500);
86
87         /* time_from_usec */
88         t3 = time_from_usec(500000);
89         ok1(t3.ts.tv_sec == 0);
90         ok1(t3.ts.tv_nsec == 500000000);
91         ok1(time_to_usec(t3) == 500000);
92
93         t3 = time_from_usec(1000000);
94         ok1(t3.ts.tv_sec == 1);
95         ok1(t3.ts.tv_nsec == 0);
96         ok1(time_to_usec(t3) == 1000000);
97
98         t3 = time_from_usec(1500000);
99         ok1(t3.ts.tv_sec == 1);
100         ok1(t3.ts.tv_nsec == 500000000);
101         ok1(time_to_usec(t3) == 1500000);
102
103         /* time_from_nsec */
104         t3 = time_from_nsec(500000000);
105         ok1(t3.ts.tv_sec == 0);
106         ok1(t3.ts.tv_nsec == 500000000);
107         ok1(time_to_nsec(t3) == 500000000);
108
109         t3 = time_from_nsec(1000000000);
110         ok1(t3.ts.tv_sec == 1);
111         ok1(t3.ts.tv_nsec == 0);
112         ok1(time_to_nsec(t3) == 1000000000);
113
114         t3 = time_from_nsec(1500000000);
115         ok1(t3.ts.tv_sec == 1);
116         ok1(t3.ts.tv_nsec == 500000000);
117         ok1(time_to_nsec(t3) == 1500000000);
118
119         /* Test wrapunder */
120         t1 = timeabs_sub(timeabs_sub(t2, time_from_msec(500)),
121                          time_from_msec(500));
122         ok1(t1.ts.tv_sec == t2.ts.tv_sec - 1);
123         ok1(t1.ts.tv_nsec == t2.ts.tv_nsec);
124
125         /* time_divide and time_multiply */
126         t4.ts.tv_nsec = 100;
127         t4.ts.tv_sec = 100;
128
129         t3 = time_divide(t4, 2);
130         ok1(t3.ts.tv_sec == 50);
131         ok1(t3.ts.tv_nsec == 50);
132
133         t3 = time_divide(t4, 100);
134         ok1(t3.ts.tv_sec == 1);
135         ok1(t3.ts.tv_nsec == 1);
136
137         t3 = time_multiply(t3, 100);
138         ok1(timerel_eq(t3, t4));
139
140         t3 = time_divide(t4, 200);
141         ok1(t3.ts.tv_sec == 0);
142         ok1(t3.ts.tv_nsec == 500000000);
143
144         /* Divide by huge number. */
145         t4.ts.tv_sec = (1U << 31) - 1;
146         t4.ts.tv_nsec = 999999999;
147         t3 = time_divide(t4, 1 << 30);
148         /* Allow us to round either way. */
149         ok1((t3.ts.tv_sec == 2 && t3.ts.tv_nsec == 0)
150             || (t3.ts.tv_sec == 1 && t3.ts.tv_nsec == 999999999));
151
152         /* Multiply by huge number. */
153         t4.ts.tv_sec = 0;
154         t4.ts.tv_nsec = 1;
155         t3 = time_multiply(t4, 1UL << 31);
156         ok1(t3.ts.tv_sec == 2);
157         ok1(t3.ts.tv_nsec == 147483648);
158
159         pipe(fds);
160
161         fflush(stdout);
162         switch (fork()) {
163         case 0:
164                 close(fds[0]);
165                 dup2(fds[1], 1);
166                 dup2(fds[1], 2);
167                 t1.ts.tv_sec = 7;
168                 t1.ts.tv_nsec = 1000000001;
169                 t2 = timeabs_check(t1, NULL);
170                 if (t2.ts.tv_sec != 8 || t2.ts.tv_nsec != 1)
171                         exit(1);
172                 t1.ts.tv_sec = -1;
173                 t1.ts.tv_nsec = 5;
174                 t2 = timeabs_check(t1, NULL);
175                 if (t2.ts.tv_sec != 0 || t2.ts.tv_nsec != 5)
176                         exit(1);
177                 t1.ts.tv_sec = 8;
178                 t1.ts.tv_nsec = 1000000002;
179                 /* We expect this to abort! */
180                 t2 = timeabs_check(t1, "abortstr");
181                 exit(1);
182                 
183         default: {
184                 char readbuf[1024];
185                 int r, len = 0;
186
187                 close(fds[1]);
188                 while ((r = read(fds[0], readbuf + len, 1023 - len)) > 0)
189                         len += r;
190                 readbuf[len] = '\0';
191                 ok1(strcmp(readbuf,
192                            "WARNING: malformed time"
193                            " 7 seconds 1000000001 ns converted to 8.000000001.\n"
194                            "WARNING: malformed time"
195                            " -1 seconds 5 ns converted to 0.000000005.\n"
196                            "abortstr: malformed time 8.1000000002\n") == 0);
197                 ok1(wait(&r) != -1);
198                 ok1(WIFEXITED(r));
199                 ok1(WEXITSTATUS(r) == 7);
200         }
201         }
202
203         return exit_status();
204 }