]> git.saurik.com Git - apple/libc.git/blob - tests/clock.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / tests / clock.c
1 #include <time.h>
2 #include <sys/time.h>
3 #include <mach/mach_time.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6
7 #include <darwintest.h>
8
9 static void burn_cpu(void){
10 static char *dummy_text = "Four score and seven years ago our fathers brought forth on this continent a new nation, conceived in liberty, and dedicated to the";
11
12 for (int i = 0; i < 100; i++){
13 char key[64]; char txt[64];
14 strncpy(txt, dummy_text, 64);
15 for (int j = 0; i < 64; i++){
16 key[j] = rand() % 1;
17 }
18 setkey(key);
19 encrypt(txt, 0);
20 encrypt(txt, 1);
21 }
22 }
23
24 T_DECL(clock_gettime_realtime, "clock_gettime(CLOCK_REALTIME, tp)")
25 {
26 struct timespec ts;
27 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_REALTIME, &ts), NULL);
28
29 struct timeval tv;
30 T_ASSERT_POSIX_ZERO(gettimeofday(&tv, NULL), NULL);
31
32 T_EXPECT_LE((unsigned long)tv.tv_sec - (unsigned long)ts.tv_sec, (unsigned long)1,
33 "gettimeofday() should return same as clock_gettime(CLOCK_REALTIME)");
34 }
35
36 T_DECL(clock_gettime_monotonic, "clock_gettime(CLOCK_MONOTONIC, tp)")
37 {
38 struct timespec ts1, ts2;
39 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC, &ts1), NULL);
40
41 sleep(1);
42
43 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC, &ts2), NULL);
44
45 uint64_t nsec1 = (uint64_t)ts1.tv_sec * NSEC_PER_SEC + (uint64_t)ts1.tv_nsec;
46 uint64_t nsec2 = (uint64_t)ts2.tv_sec * NSEC_PER_SEC + (uint64_t)ts2.tv_nsec;
47 uint64_t nsec_diff = (uint64_t)llabs((int64_t)nsec2 - (int64_t)nsec1);
48
49 T_EXPECT_GE(nsec_diff, 100 * NSEC_PER_MSEC, "clock_gettime(CLOCK_MONOTONIC) should advance at least 100ms");
50 T_EXPECT_LE(nsec_diff, 10 * NSEC_PER_SEC, "clock_gettime(CLOCK_MONOTONIC) should advance no more than 10s");
51 }
52 T_DECL(clock_gettime_monotonic_raw, "clock_gettime(CLOCK_MONOTONIC_RAW, tp)")
53 {
54 struct timespec ts1, ts2;
55 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC_RAW, &ts1), NULL);
56
57 sleep(1);
58
59 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC_RAW, &ts2), NULL);
60
61 uint64_t nsec1 = (uint64_t)ts1.tv_sec * NSEC_PER_SEC + (uint64_t)ts1.tv_nsec;
62 uint64_t nsec2 = (uint64_t)ts2.tv_sec * NSEC_PER_SEC + (uint64_t)ts2.tv_nsec;
63 uint64_t nsec_diff = (uint64_t)llabs((int64_t)nsec2 - (int64_t)nsec1);
64
65 T_EXPECT_GE(nsec_diff, 100 * NSEC_PER_MSEC, "clock_gettime(CLOCK_MONOTONIC_RAW) should advance at least 100ms");
66 T_EXPECT_LE(nsec_diff, 10 * NSEC_PER_SEC, "clock_gettime(CLOCK_MONOTONIC_RAW) should advance no more than 10s");
67 }
68
69 T_DECL(clock_gettime_uptime_raw, "clock_gettime(CLOCK_UPTIME_RAW, tp)")
70 {
71 struct timespec ts1, ts2;
72 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_UPTIME_RAW, &ts1), NULL);
73
74 sleep(1);
75
76 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_UPTIME_RAW, &ts2), NULL);
77
78 uint64_t nsec1 = (uint64_t)ts1.tv_sec * NSEC_PER_SEC + (uint64_t)ts1.tv_nsec;
79 uint64_t nsec2 = (uint64_t)ts2.tv_sec * NSEC_PER_SEC + (uint64_t)ts2.tv_nsec;
80 uint64_t nsec_diff = (uint64_t)llabs((int64_t)nsec2 - (int64_t)nsec1);
81
82 T_EXPECT_GE(nsec_diff, 100 * NSEC_PER_MSEC, "clock_gettime(CLOCK_UPTIME_RAW) should advance at least 100ms");
83 T_EXPECT_LE(nsec_diff, 10 * NSEC_PER_SEC, "clock_gettime(CLOCK_UPTIME_RAW) should advance no more than 10s");
84 }
85
86 T_DECL(clock_gettime_cputime, "clock_gettime(CLOCK_*_CPUTIME_ID, tp)")
87 {
88 struct timespec thread_ts1, thread_ts2;
89 struct timespec process_ts1, process_ts2;
90 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &process_ts1), NULL);
91 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_THREAD_CPUTIME_ID, &thread_ts1), NULL);
92
93 burn_cpu();
94
95 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &process_ts2), NULL);
96 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_THREAD_CPUTIME_ID, &thread_ts1), NULL);
97
98 uint64_t nsec1, nsec2, nsec_diff;
99
100 // CLOCK_PROCESS_CPUTIME_ID
101 nsec1 = (uint64_t)process_ts1.tv_sec * NSEC_PER_SEC + (uint64_t)process_ts1.tv_nsec;
102 nsec2 = (uint64_t)process_ts2.tv_sec * NSEC_PER_SEC + (uint64_t)process_ts2.tv_nsec;
103 nsec_diff = (uint64_t)llabs((int64_t)nsec2 - (int64_t)nsec1);
104 T_EXPECT_GE(nsec_diff, NSEC_PER_USEC, "clock_gettime(CLOCK_PROCESS_CPUTIME_ID) should advance at least 1us");
105 T_EXPECT_LE(nsec_diff, 10 * NSEC_PER_SEC, "clock_gettime(CLOCK_PROCESS_CPUTIME_ID) should advance no more than 10s");
106
107 // CLOCK_THREAD_CPUTIME_ID
108 nsec1 = (uint64_t)thread_ts1.tv_sec * NSEC_PER_SEC + (uint64_t)thread_ts1.tv_nsec;
109 nsec2 = (uint64_t)thread_ts2.tv_sec * NSEC_PER_SEC + (uint64_t)thread_ts2.tv_nsec;
110 nsec_diff = (uint64_t)llabs((int64_t)nsec2 - (int64_t)nsec1);
111 T_EXPECT_GE(nsec_diff, NSEC_PER_USEC, "clock_gettime(CLOCK_THREAD_CPUTIME_ID) should advance at least 1us");
112 T_EXPECT_LE(nsec_diff, 10 * NSEC_PER_SEC, "clock_gettime(CLOCK_THREAD_CPUTIME_ID) should advance no more than 10s");
113 }
114
115 T_DECL(clock_gettime_monotonic_comparison, "compare CLOCK_MONOTONIC to CLOCK_MONOTONIC_RAW")
116 {
117 struct timespec ts1, ts2;
118 bool should_retry = true;
119
120 retry:
121 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC, &ts1), NULL);
122 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC_RAW, &ts2), NULL);
123
124 uint64_t nsec1 = (uint64_t)ts1.tv_sec * NSEC_PER_SEC + (uint64_t)ts1.tv_nsec;
125 uint64_t nsec2 = (uint64_t)ts2.tv_sec * NSEC_PER_SEC + (uint64_t)ts2.tv_nsec;
126 uint64_t nsec_diff = (uint64_t)llabs((int64_t)nsec2 - (int64_t)nsec1);
127
128 if (should_retry && nsec_diff > nsec2/20){
129 should_retry = false;
130 goto retry;
131 }
132
133 T_EXPECT_LE(nsec_diff, nsec2/20, "CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW should be within 5%%");
134 }
135
136 T_DECL(clock_gettime_nsec_np, "clock_gettime_nsec_np()")
137 {
138 struct timespec ts;
139 uint64_t nsec, ts_nsec, diff;
140
141 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_REALTIME, &ts), NULL);
142 T_WITH_ERRNO; T_ASSERT_NE((nsec = clock_gettime_nsec_np(CLOCK_REALTIME)), (uint64_t)0, NULL);
143 ts_nsec = (uint64_t)ts.tv_sec * NSEC_PER_SEC + (uint64_t)ts.tv_nsec;
144 diff = (uint64_t)llabs((int64_t)nsec - (int64_t)ts_nsec);
145 T_EXPECT_LE(diff, 100 * NSEC_PER_MSEC, "CLOCK_REALTIME: clock_gettime() and clock_gettime_nsec_np() should be within 100ms");
146
147 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC, &ts), NULL);
148 T_WITH_ERRNO; T_ASSERT_NE((nsec = clock_gettime_nsec_np(CLOCK_MONOTONIC)), (uint64_t)0, NULL);
149 ts_nsec = (uint64_t)ts.tv_sec * NSEC_PER_SEC + (uint64_t)ts.tv_nsec;
150 diff = (uint64_t)llabs((int64_t)nsec - (int64_t)ts_nsec);
151 T_EXPECT_LE(diff, 100 * NSEC_PER_MSEC, "CLOCK_MONOTONIC: clock_gettime() and clock_gettime_nsec_np() should be within 100ms");
152
153 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC_RAW, &ts), NULL);
154 T_WITH_ERRNO; T_ASSERT_NE((nsec = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW)), (uint64_t)0, NULL);
155 ts_nsec = (uint64_t)ts.tv_sec * NSEC_PER_SEC + (uint64_t)ts.tv_nsec;
156 diff = (uint64_t)llabs((int64_t)nsec - (int64_t)ts_nsec);
157 T_EXPECT_LE(diff, 100 * NSEC_PER_MSEC, "CLOCK_MONOTONIC_RAW: clock_gettime() and clock_gettime_nsec_np() should be within 100ms");
158
159 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_UPTIME_RAW, &ts), NULL);
160 T_WITH_ERRNO; T_ASSERT_NE((nsec = clock_gettime_nsec_np(CLOCK_UPTIME_RAW)), (uint64_t)0, NULL);
161 ts_nsec = (uint64_t)ts.tv_sec * NSEC_PER_SEC + (uint64_t)ts.tv_nsec;
162 diff = (uint64_t)llabs((int64_t)nsec - (int64_t)ts_nsec);
163 T_EXPECT_LE(diff, 100 * NSEC_PER_MSEC, "CLOCK_UPTIME_RAW: clock_gettime() and clock_gettime_nsec_np() should be within 100ms");
164
165 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts), NULL);
166 T_WITH_ERRNO; T_ASSERT_NE((nsec = clock_gettime_nsec_np(CLOCK_PROCESS_CPUTIME_ID)), (uint64_t)0, NULL);
167 ts_nsec = (uint64_t)ts.tv_sec * NSEC_PER_SEC + (uint64_t)ts.tv_nsec;
168 diff = (uint64_t)llabs((int64_t)nsec - (int64_t)ts_nsec);
169 T_EXPECT_LE(diff, 100 * NSEC_PER_MSEC, "CLOCK_PROCESS_CPUTIME_ID: clock_gettime() and clock_gettime_nsec_np() should be within 100ms");
170
171 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts), NULL);
172 T_WITH_ERRNO; T_ASSERT_NE((nsec = clock_gettime_nsec_np(CLOCK_THREAD_CPUTIME_ID)), (uint64_t)0, NULL);
173 ts_nsec = (uint64_t)ts.tv_sec * NSEC_PER_SEC + (uint64_t)ts.tv_nsec;
174 diff = (uint64_t)llabs((int64_t)nsec - (int64_t)ts_nsec);
175 T_EXPECT_LE(diff, 100 * NSEC_PER_MSEC, "CLOCK_THREAD_CPUTIME_ID: clock_gettime() and clock_gettime_nsec_np() should be within 100ms");
176 }
177
178 T_DECL(clock_getres, "clock_getres()")
179 {
180 struct timespec ts;
181
182 T_ASSERT_POSIX_ZERO(clock_getres(CLOCK_REALTIME, &ts), NULL);
183 T_LOG("Resolution of CLOCK_REALTIME is %ld ns", ts.tv_nsec);
184 T_EXPECT_EQ(ts.tv_sec, (long)0, NULL);
185 T_EXPECT_GT(ts.tv_nsec, (long)0, NULL);
186
187 T_ASSERT_POSIX_ZERO(clock_getres(CLOCK_MONOTONIC, &ts), NULL);
188 T_LOG("Resolution of CLOCK_MONOTONIC is %ld ns", ts.tv_nsec);
189 T_EXPECT_EQ(ts.tv_sec, (long)0, NULL);
190 T_EXPECT_GT(ts.tv_nsec, (long)0, NULL);
191
192 T_ASSERT_POSIX_ZERO(clock_getres(CLOCK_MONOTONIC_RAW, &ts), NULL);
193 T_LOG("Resolution of CLOCK_MONOTONIC_RAW is %ld ns", ts.tv_nsec);
194 T_EXPECT_EQ(ts.tv_sec, (long)0, NULL);
195 T_EXPECT_GT(ts.tv_nsec, (long)0, NULL);
196
197 T_ASSERT_POSIX_ZERO(clock_getres(CLOCK_UPTIME_RAW, &ts), NULL);
198 T_LOG("Resolution of CLOCK_UPTIME_RAW is %ld ns", ts.tv_nsec);
199 T_EXPECT_EQ(ts.tv_sec, (long)0, NULL);
200 T_EXPECT_GT(ts.tv_nsec, (long)0, NULL);
201
202 T_ASSERT_POSIX_ZERO(clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts), NULL);
203 T_LOG("Resolution of CLOCK_MONOTONIC_RAW is %ld ns", ts.tv_nsec);
204 T_EXPECT_EQ(ts.tv_sec, (long)0, NULL);
205 T_EXPECT_GT(ts.tv_nsec, (long)0, NULL);
206
207 T_ASSERT_POSIX_ZERO(clock_getres(CLOCK_THREAD_CPUTIME_ID, &ts), NULL);
208 T_LOG("Resolution of CLOCK_MONOTONIC_RAW is %ld ns", ts.tv_nsec);
209 T_EXPECT_EQ(ts.tv_sec, (long)0, NULL);
210 T_EXPECT_GT(ts.tv_nsec, (long)0, NULL);
211 }
212
213 T_DECL(clock_settime_realtime, "clock_settime(CLOCK_REALTIME, tp)",
214 T_META("as_root", "true"))
215 {
216 struct timespec ts;
217 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_REALTIME, &ts), NULL);
218
219 time_t initial_time = ts.tv_sec;
220
221 ts.tv_nsec += 1 * NSEC_PER_SEC;
222 T_ASSERT_POSIX_ZERO(clock_settime(CLOCK_REALTIME, &ts), NULL);
223
224 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_REALTIME, &ts), NULL);
225 T_EXPECT_GT(ts.tv_sec - initial_time, (time_t)0, "time should move forward at least one second");
226 T_EXPECT_LE(ts.tv_sec - initial_time, (time_t)2, "time should move forward less than two seconds");
227 }
228 T_DECL(clock_settime_other, "clock_settime(CLOCK_*, tp)",
229 T_META("as_root", "true"))
230 {
231 struct timespec ts;;
232 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_MONOTONIC_RAW, &ts), NULL);
233 T_EXPECT_EQ(clock_settime(CLOCK_MONOTONIC_RAW, &ts), -1, NULL);
234 T_EXPECT_EQ(errno, EINVAL, NULL);
235
236 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts), NULL);
237 T_EXPECT_EQ(clock_settime(CLOCK_PROCESS_CPUTIME_ID, &ts), -1, NULL);
238 T_EXPECT_EQ(errno, EINVAL, NULL);
239
240 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_UPTIME_RAW, &ts), NULL);
241 T_EXPECT_EQ(clock_settime(CLOCK_UPTIME_RAW, &ts), -1, NULL);
242 T_EXPECT_EQ(errno, EINVAL, NULL);
243
244 T_ASSERT_POSIX_ZERO(clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts), NULL);
245 T_EXPECT_EQ(clock_settime(CLOCK_THREAD_CPUTIME_ID, &ts), -1, NULL);
246 T_EXPECT_EQ(errno, EINVAL, NULL);
247 }