OSDN Git Service

Fix flaky test of timer_create_multiple in L.
[android-x86/bionic.git] / tests / time_test.cpp
1 /*
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
17 #include <time.h>
18
19 #include <errno.h>
20 #include <features.h>
21 #include <gtest/gtest.h>
22 #include <pthread.h>
23 #include <signal.h>
24 #include <stdatomic.h>
25 #include <sys/syscall.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28
29 #include "ScopedSignalHandler.h"
30
31 TEST(time, gmtime) {
32   time_t t = 0;
33   tm* broken_down = gmtime(&t);
34   ASSERT_TRUE(broken_down != NULL);
35   ASSERT_EQ(0, broken_down->tm_sec);
36   ASSERT_EQ(0, broken_down->tm_min);
37   ASSERT_EQ(0, broken_down->tm_hour);
38   ASSERT_EQ(1, broken_down->tm_mday);
39   ASSERT_EQ(0, broken_down->tm_mon);
40   ASSERT_EQ(1970, broken_down->tm_year + 1900);
41 }
42
43 static void* gmtime_no_stack_overflow_14313703_fn(void*) {
44   const char* original_tz = getenv("TZ");
45   // Ensure we'll actually have to enter tzload by using a time zone that doesn't exist.
46   setenv("TZ", "gmtime_stack_overflow_14313703", 1);
47   tzset();
48   if (original_tz != NULL) {
49     setenv("TZ", original_tz, 1);
50   }
51   tzset();
52   return NULL;
53 }
54
55 TEST(time, gmtime_no_stack_overflow_14313703) {
56   // Is it safe to call tzload on a thread with a small stack?
57   // http://b/14313703
58   // https://code.google.com/p/android/issues/detail?id=61130
59   pthread_attr_t attributes;
60   ASSERT_EQ(0, pthread_attr_init(&attributes));
61 #if defined(__BIONIC__)
62   ASSERT_EQ(0, pthread_attr_setstacksize(&attributes, PTHREAD_STACK_MIN));
63 #else
64   // PTHREAD_STACK_MIN not currently in the host GCC sysroot.
65   ASSERT_EQ(0, pthread_attr_setstacksize(&attributes, 4 * getpagesize()));
66 #endif
67
68   pthread_t t;
69   ASSERT_EQ(0, pthread_create(&t, &attributes, gmtime_no_stack_overflow_14313703_fn, NULL));
70   void* result;
71   ASSERT_EQ(0, pthread_join(t, &result));
72 }
73
74 TEST(time, mktime_10310929) {
75   struct tm t;
76   memset(&t, 0, sizeof(tm));
77   t.tm_year = 200;
78   t.tm_mon = 2;
79   t.tm_mday = 10;
80
81 #if !defined(__LP64__)
82   // 32-bit bionic stupidly had a signed 32-bit time_t.
83   ASSERT_EQ(-1, mktime(&t));
84 #else
85   // Everyone else should be using a signed 64-bit time_t.
86   ASSERT_GE(sizeof(time_t) * 8, 64U);
87
88   setenv("TZ", "America/Los_Angeles", 1);
89   tzset();
90   ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&t));
91
92   setenv("TZ", "UTC", 1);
93   tzset();
94   ASSERT_EQ(static_cast<time_t>(4108320000U), mktime(&t));
95 #endif
96 }
97
98 TEST(time, strftime) {
99   setenv("TZ", "UTC", 1);
100
101   struct tm t;
102   memset(&t, 0, sizeof(tm));
103   t.tm_year = 200;
104   t.tm_mon = 2;
105   t.tm_mday = 10;
106
107   char buf[64];
108
109   // Seconds since the epoch.
110 #if defined(__BIONIC__) || defined(__LP64__) // Not 32-bit glibc.
111   EXPECT_EQ(10U, strftime(buf, sizeof(buf), "%s", &t));
112   EXPECT_STREQ("4108320000", buf);
113 #endif
114
115   // Date and time as text.
116   EXPECT_EQ(24U, strftime(buf, sizeof(buf), "%c", &t));
117   EXPECT_STREQ("Sun Mar 10 00:00:00 2100", buf);
118 }
119
120 TEST(time, strptime) {
121   setenv("TZ", "UTC", 1);
122
123   struct tm t;
124   char buf[64];
125
126   memset(&t, 0, sizeof(t));
127   strptime("11:14", "%R", &t);
128   strftime(buf, sizeof(buf), "%H:%M", &t);
129   EXPECT_STREQ("11:14", buf);
130
131   memset(&t, 0, sizeof(t));
132   strptime("09:41:53", "%T", &t);
133   strftime(buf, sizeof(buf), "%H:%M:%S", &t);
134   EXPECT_STREQ("09:41:53", buf);
135 }
136
137 void SetTime(timer_t t, time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
138   itimerspec ts;
139   ts.it_value.tv_sec = value_s;
140   ts.it_value.tv_nsec = value_ns;
141   ts.it_interval.tv_sec = interval_s;
142   ts.it_interval.tv_nsec = interval_ns;
143   ASSERT_EQ(0, timer_settime(t, 0, &ts, NULL));
144 }
145
146 static void NoOpNotifyFunction(sigval_t) {
147 }
148
149 TEST(time, timer_create) {
150   sigevent_t se;
151   memset(&se, 0, sizeof(se));
152   se.sigev_notify = SIGEV_THREAD;
153   se.sigev_notify_function = NoOpNotifyFunction;
154   timer_t timer_id;
155   ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
156
157   int pid = fork();
158   ASSERT_NE(-1, pid) << strerror(errno);
159
160   if (pid == 0) {
161     // Timers are not inherited by the child.
162     ASSERT_EQ(-1, timer_delete(timer_id));
163     ASSERT_EQ(EINVAL, errno);
164     _exit(0);
165   }
166
167   int status;
168   ASSERT_EQ(pid, waitpid(pid, &status, 0));
169   ASSERT_TRUE(WIFEXITED(status));
170   ASSERT_EQ(0, WEXITSTATUS(status));
171
172   ASSERT_EQ(0, timer_delete(timer_id));
173 }
174
175 static int timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
176 static void timer_create_SIGEV_SIGNAL_signal_handler(int signal_number) {
177   ++timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
178   ASSERT_EQ(SIGUSR1, signal_number);
179 }
180
181 TEST(time, timer_create_SIGEV_SIGNAL) {
182   sigevent_t se;
183   memset(&se, 0, sizeof(se));
184   se.sigev_notify = SIGEV_SIGNAL;
185   se.sigev_signo = SIGUSR1;
186
187   timer_t timer_id;
188   ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
189
190   timer_create_SIGEV_SIGNAL_signal_handler_invocation_count = 0;
191   ScopedSignalHandler ssh(SIGUSR1, timer_create_SIGEV_SIGNAL_signal_handler);
192
193   ASSERT_EQ(0, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
194
195   itimerspec ts;
196   ts.it_value.tv_sec =  0;
197   ts.it_value.tv_nsec = 1;
198   ts.it_interval.tv_sec = 0;
199   ts.it_interval.tv_nsec = 0;
200   ASSERT_EQ(0, timer_settime(timer_id, TIMER_ABSTIME, &ts, NULL));
201
202   usleep(500000);
203   ASSERT_EQ(1, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
204 }
205
206 struct Counter {
207  private:
208   atomic_int value;
209   timer_t timer_id;
210   sigevent_t se;
211   bool timer_valid;
212
213   void Create() {
214     ASSERT_FALSE(timer_valid);
215     ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &timer_id));
216     timer_valid = true;
217   }
218
219  public:
220   Counter(void (*fn)(sigval_t)) : value(ATOMIC_VAR_INIT(0)), timer_valid(false) {
221     memset(&se, 0, sizeof(se));
222     se.sigev_notify = SIGEV_THREAD;
223     se.sigev_notify_function = fn;
224     se.sigev_value.sival_ptr = this;
225     Create();
226   }
227
228   void DeleteTimer() {
229     ASSERT_TRUE(timer_valid);
230     ASSERT_EQ(0, timer_delete(timer_id));
231     timer_valid = false;
232   }
233
234   ~Counter() {
235     if (timer_valid) {
236       DeleteTimer();
237     }
238   }
239
240   int Value() {
241     return atomic_load(&value);
242   }
243
244   void SetTime(time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
245     ::SetTime(timer_id, value_s, value_ns, interval_s, interval_ns);
246   }
247
248   bool ValueUpdated() {
249     int current_value = atomic_load(&value);
250     time_t start = time(NULL);
251     while (current_value == atomic_load(&value) && (time(NULL) - start) < 5) {
252     }
253     return current_value != atomic_load(&value);
254   }
255
256   static void CountNotifyFunction(sigval_t value) {
257     Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
258     atomic_fetch_add(&cd->value, 1);
259   }
260
261   static void CountAndDisarmNotifyFunction(sigval_t value) {
262     Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
263     atomic_fetch_add(&cd->value, 1);
264
265     // Setting the initial expiration time to 0 disarms the timer.
266     cd->SetTime(0, 0, 1, 0);
267   }
268 };
269
270 TEST(time, timer_settime_0) {
271   Counter counter(Counter::CountAndDisarmNotifyFunction);
272   ASSERT_EQ(0, counter.Value());
273
274   counter.SetTime(0, 1, 1, 0);
275   usleep(500000);
276
277   // The count should just be 1 because we disarmed the timer the first time it fired.
278   ASSERT_EQ(1, counter.Value());
279 }
280
281 TEST(time, timer_settime_repeats) {
282   Counter counter(Counter::CountNotifyFunction);
283   ASSERT_EQ(0, counter.Value());
284
285   counter.SetTime(0, 1, 0, 10);
286   ASSERT_TRUE(counter.ValueUpdated());
287   ASSERT_TRUE(counter.ValueUpdated());
288   ASSERT_TRUE(counter.ValueUpdated());
289   counter.DeleteTimer();
290   // Add a sleep as other threads may be calling the callback function when the timer is deleted.
291   usleep(500000);
292 }
293
294 static int timer_create_NULL_signal_handler_invocation_count;
295 static void timer_create_NULL_signal_handler(int signal_number) {
296   ++timer_create_NULL_signal_handler_invocation_count;
297   ASSERT_EQ(SIGALRM, signal_number);
298 }
299
300 TEST(time, timer_create_NULL) {
301   // A NULL sigevent* is equivalent to asking for SIGEV_SIGNAL for SIGALRM.
302   timer_t timer_id;
303   ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id));
304
305   timer_create_NULL_signal_handler_invocation_count = 0;
306   ScopedSignalHandler ssh(SIGALRM, timer_create_NULL_signal_handler);
307
308   ASSERT_EQ(0, timer_create_NULL_signal_handler_invocation_count);
309
310   SetTime(timer_id, 0, 1, 0, 0);
311   usleep(500000);
312
313   ASSERT_EQ(1, timer_create_NULL_signal_handler_invocation_count);
314 }
315
316 TEST(time, timer_create_EINVAL) {
317   clockid_t invalid_clock = 16;
318
319   // A SIGEV_SIGNAL timer is easy; the kernel does all that.
320   timer_t timer_id;
321   ASSERT_EQ(-1, timer_create(invalid_clock, NULL, &timer_id));
322   ASSERT_EQ(EINVAL, errno);
323
324   // A SIGEV_THREAD timer is more interesting because we have stuff to clean up.
325   sigevent_t se;
326   memset(&se, 0, sizeof(se));
327   se.sigev_notify = SIGEV_THREAD;
328   se.sigev_notify_function = NoOpNotifyFunction;
329   ASSERT_EQ(-1, timer_create(invalid_clock, &se, &timer_id));
330   ASSERT_EQ(EINVAL, errno);
331 }
332
333 TEST(time, timer_delete_multiple) {
334   timer_t timer_id;
335   ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id));
336   ASSERT_EQ(0, timer_delete(timer_id));
337   ASSERT_EQ(-1, timer_delete(timer_id));
338   ASSERT_EQ(EINVAL, errno);
339
340   sigevent_t se;
341   memset(&se, 0, sizeof(se));
342   se.sigev_notify = SIGEV_THREAD;
343   se.sigev_notify_function = NoOpNotifyFunction;
344   ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
345   ASSERT_EQ(0, timer_delete(timer_id));
346   ASSERT_EQ(-1, timer_delete(timer_id));
347   ASSERT_EQ(EINVAL, errno);
348 }
349
350 TEST(time, timer_create_multiple) {
351   Counter counter1(Counter::CountNotifyFunction);
352   Counter counter2(Counter::CountNotifyFunction);
353   Counter counter3(Counter::CountNotifyFunction);
354
355   ASSERT_EQ(0, counter1.Value());
356   ASSERT_EQ(0, counter2.Value());
357   ASSERT_EQ(0, counter3.Value());
358
359   counter2.SetTime(0, 500000000, 0, 0);
360   sleep(1);
361
362   EXPECT_EQ(0, counter1.Value());
363   EXPECT_EQ(1, counter2.Value());
364   EXPECT_EQ(0, counter3.Value());
365 }
366
367 // Test to verify that disarming a repeatable timer disables the callbacks.
368 TEST(time, timer_disarm_terminates) {
369   Counter counter(Counter::CountNotifyFunction);
370   ASSERT_EQ(0, counter.Value());
371
372   counter.SetTime(0, 1, 0, 1);
373   ASSERT_TRUE(counter.ValueUpdated());
374   ASSERT_TRUE(counter.ValueUpdated());
375   ASSERT_TRUE(counter.ValueUpdated());
376
377   counter.SetTime(0, 0, 0, 0);
378   // Add a sleep as the kernel may have pending events when the timer is disarmed.
379   usleep(500000);
380   int value = counter.Value();
381   usleep(500000);
382
383   // Verify the counter has not been incremented.
384   ASSERT_EQ(value, counter.Value());
385 }
386
387 // Test to verify that deleting a repeatable timer disables the callbacks.
388 TEST(time, timer_delete_terminates) {
389   Counter counter(Counter::CountNotifyFunction);
390   ASSERT_EQ(0, counter.Value());
391
392   counter.SetTime(0, 1, 0, 1);
393   ASSERT_TRUE(counter.ValueUpdated());
394   ASSERT_TRUE(counter.ValueUpdated());
395   ASSERT_TRUE(counter.ValueUpdated());
396
397   counter.DeleteTimer();
398   // Add a sleep as other threads may be calling the callback function when the timer is deleted.
399   usleep(500000);
400   int value = counter.Value();
401   usleep(500000);
402
403   // Verify the counter has not been incremented.
404   ASSERT_EQ(value, counter.Value());
405 }
406
407 struct TimerDeleteData {
408   timer_t timer_id;
409   pthread_t thread_id;
410   volatile bool complete;
411 };
412
413 static void TimerDeleteCallback(sigval_t value) {
414   TimerDeleteData* tdd = reinterpret_cast<TimerDeleteData*>(value.sival_ptr);
415
416   tdd->thread_id = pthread_self();
417   timer_delete(tdd->timer_id);
418   tdd->complete = true;
419 }
420
421 TEST(time, timer_delete_from_timer_thread) {
422   TimerDeleteData tdd;
423   sigevent_t se;
424
425   memset(&se, 0, sizeof(se));
426   se.sigev_notify = SIGEV_THREAD;
427   se.sigev_notify_function = TimerDeleteCallback;
428   se.sigev_value.sival_ptr = &tdd;
429
430   tdd.complete = false;
431   ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &tdd.timer_id));
432
433   itimerspec ts;
434   ts.it_value.tv_sec = 1;
435   ts.it_value.tv_nsec = 0;
436   ts.it_interval.tv_sec = 0;
437   ts.it_interval.tv_nsec = 0;
438   ASSERT_EQ(0, timer_settime(tdd.timer_id, 0, &ts, NULL));
439
440   time_t cur_time = time(NULL);
441   while (!tdd.complete && (time(NULL) - cur_time) < 5);
442   ASSERT_TRUE(tdd.complete);
443
444 #if defined(__BIONIC__)
445   // Since bionic timers are implemented by creating a thread to handle the
446   // callback, verify that the thread actually completes.
447   cur_time = time(NULL);
448   while (pthread_detach(tdd.thread_id) != ESRCH && (time(NULL) - cur_time) < 5);
449   ASSERT_EQ(ESRCH, pthread_detach(tdd.thread_id));
450 #endif
451 }
452
453 TEST(time, clock_gettime) {
454   // Try to ensure that our vdso clock_gettime is working.
455   timespec ts1;
456   ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts1));
457   timespec ts2;
458   ASSERT_EQ(0, syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts2));
459
460   // What's the difference between the two?
461   ts2.tv_sec -= ts1.tv_sec;
462   ts2.tv_nsec -= ts1.tv_nsec;
463   if (ts2.tv_nsec < 0) {
464     --ts2.tv_sec;
465     ts2.tv_nsec += 1000000000;
466   }
467
468   // Should be less than (a very generous, to try to avoid flakiness) 1000000ns.
469   ASSERT_EQ(0, ts2.tv_sec);
470   ASSERT_LT(ts2.tv_nsec, 1000000);
471 }