blob: 7a2116bc79959f14ec4f6fa07190864c127695ce [file] [log] [blame]
Elliott Hughese0175ca2013-03-14 14:38:08 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Elliott Hughes4b558f52014-03-04 15:58:02 -080017#include <time.h>
18
19#include <errno.h>
Elliott Hughese0175ca2013-03-14 14:38:08 -070020#include <features.h>
21#include <gtest/gtest.h>
Elliott Hughes4b558f52014-03-04 15:58:02 -080022#include <signal.h>
Brian Carlstrombe1d91d2014-03-08 15:05:26 -080023#include <sys/types.h>
24#include <sys/wait.h>
Elliott Hughese0175ca2013-03-14 14:38:08 -070025
Elliott Hughes4b558f52014-03-04 15:58:02 -080026#include "ScopedSignalHandler.h"
Elliott Hughese0175ca2013-03-14 14:38:08 -070027
Christopher Ferrisf04935c2013-12-20 18:43:21 -080028#if defined(__BIONIC__) // mktime_tz is a bionic extension.
Elliott Hughese0175ca2013-03-14 14:38:08 -070029#include <libc/private/bionic_time.h>
Christopher Ferrisf04935c2013-12-20 18:43:21 -080030#endif // __BIONIC__
31
Elliott Hughese0175ca2013-03-14 14:38:08 -070032TEST(time, mktime_tz) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -080033#if defined(__BIONIC__)
Elliott Hughese0175ca2013-03-14 14:38:08 -070034 struct tm epoch;
35 memset(&epoch, 0, sizeof(tm));
36 epoch.tm_year = 1970 - 1900;
37 epoch.tm_mon = 1;
38 epoch.tm_mday = 1;
39
40 // Alphabetically first. Coincidentally equivalent to UTC.
41 ASSERT_EQ(2678400, mktime_tz(&epoch, "Africa/Abidjan"));
42
43 // Alphabetically last. Coincidentally equivalent to UTC.
44 ASSERT_EQ(2678400, mktime_tz(&epoch, "Zulu"));
45
46 // Somewhere in the middle, not UTC.
47 ASSERT_EQ(2707200, mktime_tz(&epoch, "America/Los_Angeles"));
48
49 // Missing. Falls back to UTC.
50 ASSERT_EQ(2678400, mktime_tz(&epoch, "PST"));
Christopher Ferrisf04935c2013-12-20 18:43:21 -080051#else // __BIONIC__
52 GTEST_LOG_(INFO) << "This test does nothing.\n";
53#endif // __BIONIC__
Elliott Hughese0175ca2013-03-14 14:38:08 -070054}
Elliott Hughesee178bf2013-07-12 11:25:20 -070055
56TEST(time, gmtime) {
57 time_t t = 0;
58 tm* broken_down = gmtime(&t);
59 ASSERT_TRUE(broken_down != NULL);
60 ASSERT_EQ(0, broken_down->tm_sec);
61 ASSERT_EQ(0, broken_down->tm_min);
62 ASSERT_EQ(0, broken_down->tm_hour);
63 ASSERT_EQ(1, broken_down->tm_mday);
64 ASSERT_EQ(0, broken_down->tm_mon);
65 ASSERT_EQ(1970, broken_down->tm_year + 1900);
66}
Elliott Hughes7843d442013-08-22 11:37:32 -070067
Elliott Hughes7843d442013-08-22 11:37:32 -070068TEST(time, mktime_10310929) {
69 struct tm t;
70 memset(&t, 0, sizeof(tm));
71 t.tm_year = 200;
72 t.tm_mon = 2;
73 t.tm_mday = 10;
74
Elliott Hughes0c401522013-10-18 16:21:54 -070075#if !defined(__LP64__)
76 // 32-bit bionic stupidly had a signed 32-bit time_t.
Elliott Hughes7843d442013-08-22 11:37:32 -070077 ASSERT_EQ(-1, mktime(&t));
Christopher Ferrisf04935c2013-12-20 18:43:21 -080078#if defined(__BIONIC__)
Elliott Hughes7843d442013-08-22 11:37:32 -070079 ASSERT_EQ(-1, mktime_tz(&t, "UTC"));
Christopher Ferrisf04935c2013-12-20 18:43:21 -080080#endif
Elliott Hughes0c401522013-10-18 16:21:54 -070081#else
82 // Everyone else should be using a signed 64-bit time_t.
83 ASSERT_GE(sizeof(time_t) * 8, 64U);
84
85 setenv("TZ", "America/Los_Angeles", 1);
86 tzset();
87 ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&t));
Christopher Ferrisf04935c2013-12-20 18:43:21 -080088#if defined(__BIONIC__)
Elliott Hughes0c401522013-10-18 16:21:54 -070089 ASSERT_EQ(static_cast<time_t>(4108320000U), mktime_tz(&t, "UTC"));
Christopher Ferrisf04935c2013-12-20 18:43:21 -080090#endif
Elliott Hughes0c401522013-10-18 16:21:54 -070091
92 setenv("TZ", "UTC", 1);
93 tzset();
94 ASSERT_EQ(static_cast<time_t>(4108320000U), mktime(&t));
Christopher Ferrisf04935c2013-12-20 18:43:21 -080095#if defined(__BIONIC__)
Elliott Hughes0c401522013-10-18 16:21:54 -070096 ASSERT_EQ(static_cast<time_t>(4108348800U), mktime_tz(&t, "America/Los_Angeles"));
97#endif
Elliott Hughes7843d442013-08-22 11:37:32 -070098#endif
Christopher Ferrisf04935c2013-12-20 18:43:21 -080099}
Elliott Hughes4b558f52014-03-04 15:58:02 -0800100
101void SetTime(timer_t t, time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
102 itimerspec ts;
103 ts.it_value.tv_sec = value_s;
104 ts.it_value.tv_nsec = value_ns;
105 ts.it_interval.tv_sec = interval_s;
106 ts.it_interval.tv_nsec = interval_ns;
107 ASSERT_EQ(0, timer_settime(t, TIMER_ABSTIME, &ts, NULL));
108}
109
110static void NoOpNotifyFunction(sigval_t) {
111}
112
113TEST(time, timer_create) {
114 sigevent_t se;
115 memset(&se, 0, sizeof(se));
116 se.sigev_notify = SIGEV_THREAD;
117 se.sigev_notify_function = NoOpNotifyFunction;
118 timer_t timer_id;
119 ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
120
121 int pid = fork();
122 ASSERT_NE(-1, pid) << strerror(errno);
123
124 if (pid == 0) {
125 // Timers are not inherited by the child.
126 ASSERT_EQ(-1, timer_delete(timer_id));
127 ASSERT_EQ(EINVAL, errno);
128 _exit(0);
129 }
130
131 int status;
132 ASSERT_EQ(pid, waitpid(pid, &status, 0));
133 ASSERT_TRUE(WIFEXITED(status));
134 ASSERT_EQ(0, WEXITSTATUS(status));
135
136 ASSERT_EQ(0, timer_delete(timer_id));
137}
138
139static int timer_create_SIGEV_SIGNAL_signal_handler_invocation_count = 0;
140static void timer_create_SIGEV_SIGNAL_signal_handler(int signal_number) {
141 ++timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
142 ASSERT_EQ(SIGUSR1, signal_number);
143}
144
145TEST(time, timer_create_SIGEV_SIGNAL) {
146 sigevent_t se;
147 memset(&se, 0, sizeof(se));
148 se.sigev_notify = SIGEV_SIGNAL;
149 se.sigev_signo = SIGUSR1;
150
151 timer_t timer_id;
152 ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
153
154 ScopedSignalHandler ssh(SIGUSR1, timer_create_SIGEV_SIGNAL_signal_handler);
155
156 ASSERT_EQ(0, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
157
158 itimerspec ts;
159 ts.it_value.tv_sec = 0;
160 ts.it_value.tv_nsec = 1;
161 ts.it_interval.tv_sec = 0;
162 ts.it_interval.tv_nsec = 0;
163 ASSERT_EQ(0, timer_settime(timer_id, TIMER_ABSTIME, &ts, NULL));
164
165 usleep(500000);
166 ASSERT_EQ(1, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
167}
168
169struct Counter {
170 volatile int value;
171 timer_t timer_id;
172 sigevent_t se;
173
174 Counter(void (*fn)(sigval_t)) : value(0) {
175 memset(&se, 0, sizeof(se));
176 se.sigev_notify = SIGEV_THREAD;
177 se.sigev_notify_function = fn;
178 se.sigev_value.sival_ptr = this;
179 }
180
181 void Create() {
182 ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &timer_id));
183 }
184
185 ~Counter() {
186 if (timer_delete(timer_id) != 0) {
187 abort();
188 }
189 }
190
191 static void CountNotifyFunction(sigval_t value) {
192 Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
193 ++cd->value;
194 }
195
196 static void CountAndDisarmNotifyFunction(sigval_t value) {
197 Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
198 ++cd->value;
199
200 // Setting the initial expiration time to 0 disarms the timer.
201 SetTime(cd->timer_id, 0, 0, 1, 0);
202 }
203};
204
205TEST(time, timer_settime_0) {
206 Counter counter(Counter::CountAndDisarmNotifyFunction);
207 counter.Create();
208
209 ASSERT_EQ(0, counter.value);
210
211 SetTime(counter.timer_id, 0, 1, 1, 0);
212 usleep(500000);
213
214 // The count should just be 1 because we disarmed the timer the first time it fired.
215 ASSERT_EQ(1, counter.value);
216}
217
218TEST(time, timer_settime_repeats) {
219 Counter counter(Counter::CountNotifyFunction);
220 counter.Create();
221
222 ASSERT_EQ(0, counter.value);
223
224 SetTime(counter.timer_id, 0, 1, 0, 10);
225 usleep(500000);
226
227 // The count should just be > 1 because we let the timer repeat.
228 ASSERT_GT(counter.value, 1);
229}
230
231static int timer_create_NULL_signal_handler_invocation_count = 0;
232static void timer_create_NULL_signal_handler(int signal_number) {
233 ++timer_create_NULL_signal_handler_invocation_count;
234 ASSERT_EQ(SIGALRM, signal_number);
235}
236
237TEST(time, timer_create_NULL) {
238 // A NULL sigevent* is equivalent to asking for SIGEV_SIGNAL for SIGALRM.
239 timer_t timer_id;
240 ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id));
241
242 ScopedSignalHandler ssh(SIGALRM, timer_create_NULL_signal_handler);
243
244 ASSERT_EQ(0, timer_create_NULL_signal_handler_invocation_count);
245
246 SetTime(timer_id, 0, 1, 0, 0);
247 usleep(500000);
248
249 ASSERT_EQ(1, timer_create_NULL_signal_handler_invocation_count);
250}
251
252TEST(time, timer_create_EINVAL) {
253 clockid_t invalid_clock = 16;
254
255 // A SIGEV_SIGNAL timer is easy; the kernel does all that.
256 timer_t timer_id;
257 ASSERT_EQ(-1, timer_create(invalid_clock, NULL, &timer_id));
258 ASSERT_EQ(EINVAL, errno);
259
260 // A SIGEV_THREAD timer is more interesting because we have stuff to clean up.
261 sigevent_t se;
262 memset(&se, 0, sizeof(se));
263 se.sigev_notify = SIGEV_THREAD;
264 se.sigev_notify_function = NoOpNotifyFunction;
265 ASSERT_EQ(-1, timer_create(invalid_clock, &se, &timer_id));
266 ASSERT_EQ(EINVAL, errno);
267}
268
269TEST(time, timer_delete_multiple) {
270 timer_t timer_id;
271 ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id));
272 ASSERT_EQ(0, timer_delete(timer_id));
273 ASSERT_EQ(-1, timer_delete(timer_id));
274 ASSERT_EQ(EINVAL, errno);
275
276 sigevent_t se;
277 memset(&se, 0, sizeof(se));
278 se.sigev_notify = SIGEV_THREAD;
279 se.sigev_notify_function = NoOpNotifyFunction;
280 ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
281 ASSERT_EQ(0, timer_delete(timer_id));
282 ASSERT_EQ(-1, timer_delete(timer_id));
283 ASSERT_EQ(EINVAL, errno);
284}
285
286TEST(time, timer_create_multiple) {
287 Counter counter1(Counter::CountNotifyFunction);
288 counter1.Create();
289 Counter counter2(Counter::CountNotifyFunction);
290 counter2.Create();
291 Counter counter3(Counter::CountNotifyFunction);
292 counter3.Create();
293
294 ASSERT_EQ(0, counter1.value);
295 ASSERT_EQ(0, counter2.value);
296 ASSERT_EQ(0, counter3.value);
297
298 SetTime(counter2.timer_id, 0, 1, 0, 0);
299 usleep(500000);
300
301 EXPECT_EQ(0, counter1.value);
302 EXPECT_EQ(1, counter2.value);
303 EXPECT_EQ(0, counter3.value);
304}