]>
Commit | Line | Data |
---|---|---|
974e3884 A |
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 | } |