time_test.cpp revision a9cac4c87a4ea3e6d1c0a1159909bf0e209a61a7
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 <gtest/gtest.h>
21#include <pthread.h>
22#include <signal.h>
23#include <sys/syscall.h>
24#include <sys/types.h>
25#include <sys/wait.h>
26#include <unistd.h>
27#include <atomic>
28
29#include "ScopedSignalHandler.h"
30
31#include "private/bionic_constants.h"
32
33TEST(time, gmtime) {
34  time_t t = 0;
35  tm* broken_down = gmtime(&t);
36  ASSERT_TRUE(broken_down != NULL);
37  ASSERT_EQ(0, broken_down->tm_sec);
38  ASSERT_EQ(0, broken_down->tm_min);
39  ASSERT_EQ(0, broken_down->tm_hour);
40  ASSERT_EQ(1, broken_down->tm_mday);
41  ASSERT_EQ(0, broken_down->tm_mon);
42  ASSERT_EQ(1970, broken_down->tm_year + 1900);
43}
44
45static void* gmtime_no_stack_overflow_14313703_fn(void*) {
46  const char* original_tz = getenv("TZ");
47  // Ensure we'll actually have to enter tzload by using a time zone that doesn't exist.
48  setenv("TZ", "gmtime_stack_overflow_14313703", 1);
49  tzset();
50  if (original_tz != NULL) {
51    setenv("TZ", original_tz, 1);
52  }
53  tzset();
54  return NULL;
55}
56
57TEST(time, gmtime_no_stack_overflow_14313703) {
58  // Is it safe to call tzload on a thread with a small stack?
59  // http://b/14313703
60  // https://code.google.com/p/android/issues/detail?id=61130
61  pthread_attr_t attributes;
62  ASSERT_EQ(0, pthread_attr_init(&attributes));
63#if defined(__BIONIC__)
64  ASSERT_EQ(0, pthread_attr_setstacksize(&attributes, PTHREAD_STACK_MIN));
65#else
66  // PTHREAD_STACK_MIN not currently in the host GCC sysroot.
67  ASSERT_EQ(0, pthread_attr_setstacksize(&attributes, 4 * getpagesize()));
68#endif
69
70  pthread_t t;
71  ASSERT_EQ(0, pthread_create(&t, &attributes, gmtime_no_stack_overflow_14313703_fn, NULL));
72  void* result;
73  ASSERT_EQ(0, pthread_join(t, &result));
74}
75
76TEST(time, mktime_empty_TZ) {
77  // tzcode used to have a bug where it didn't reinitialize some internal state.
78
79  // Choose a time where DST is set.
80  struct tm t;
81  memset(&t, 0, sizeof(tm));
82  t.tm_year = 1980 - 1900;
83  t.tm_mon = 6;
84  t.tm_mday = 2;
85
86  setenv("TZ", "America/Los_Angeles", 1);
87  tzset();
88  ASSERT_EQ(static_cast<time_t>(331372800U), mktime(&t));
89
90  memset(&t, 0, sizeof(tm));
91  t.tm_year = 1980 - 1900;
92  t.tm_mon = 6;
93  t.tm_mday = 2;
94
95  setenv("TZ", "", 1); // Implies UTC.
96  tzset();
97  ASSERT_EQ(static_cast<time_t>(331344000U), mktime(&t));
98}
99
100TEST(time, mktime_10310929) {
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#if !defined(__LP64__)
108  // 32-bit bionic stupidly had a signed 32-bit time_t.
109  ASSERT_EQ(-1, mktime(&t));
110#else
111  // Everyone else should be using a signed 64-bit time_t.
112  ASSERT_GE(sizeof(time_t) * 8, 64U);
113
114  setenv("TZ", "America/Los_Angeles", 1);
115  tzset();
116  ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&t));
117
118  setenv("TZ", "UTC", 1);
119  tzset();
120  ASSERT_EQ(static_cast<time_t>(4108320000U), mktime(&t));
121#endif
122}
123
124TEST(time, strftime) {
125  setenv("TZ", "UTC", 1);
126
127  struct tm t;
128  memset(&t, 0, sizeof(tm));
129  t.tm_year = 200;
130  t.tm_mon = 2;
131  t.tm_mday = 10;
132
133  char buf[64];
134
135  // Seconds since the epoch.
136#if defined(__BIONIC__) || defined(__LP64__) // Not 32-bit glibc.
137  EXPECT_EQ(10U, strftime(buf, sizeof(buf), "%s", &t));
138  EXPECT_STREQ("4108320000", buf);
139#endif
140
141  // Date and time as text.
142  EXPECT_EQ(24U, strftime(buf, sizeof(buf), "%c", &t));
143  EXPECT_STREQ("Sun Mar 10 00:00:00 2100", buf);
144}
145
146TEST(time, strftime_null_tm_zone) {
147  // Netflix on Nexus Player wouldn't start (http://b/25170306).
148  struct tm t;
149  memset(&t, 0, sizeof(tm));
150
151  char buf[64];
152
153  setenv("TZ", "America/Los_Angeles", 1);
154  tzset();
155
156  t.tm_isdst = 0; // "0 if Daylight Savings Time is not in effect".
157  EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
158  EXPECT_STREQ("<PST>", buf);
159
160#if defined(__BIONIC__) // glibc 2.19 only copes with tm_isdst being 0 and 1.
161  t.tm_isdst = 2; // "positive if Daylight Savings Time is in effect"
162  EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
163  EXPECT_STREQ("<PDT>", buf);
164
165  t.tm_isdst = -123; // "and negative if the information is not available".
166  EXPECT_EQ(2U, strftime(buf, sizeof(buf), "<%Z>", &t));
167  EXPECT_STREQ("<>", buf);
168#endif
169
170  setenv("TZ", "UTC", 1);
171  tzset();
172
173  t.tm_isdst = 0;
174  EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
175  EXPECT_STREQ("<UTC>", buf);
176
177#if defined(__BIONIC__) // glibc 2.19 thinks UTC DST is "UTC".
178  t.tm_isdst = 1; // UTC has no DST.
179  EXPECT_EQ(2U, strftime(buf, sizeof(buf), "<%Z>", &t));
180  EXPECT_STREQ("<>", buf);
181#endif
182}
183
184TEST(time, strptime) {
185  setenv("TZ", "UTC", 1);
186
187  struct tm t;
188  char buf[64];
189
190  memset(&t, 0, sizeof(t));
191  strptime("11:14", "%R", &t);
192  strftime(buf, sizeof(buf), "%H:%M", &t);
193  EXPECT_STREQ("11:14", buf);
194
195  memset(&t, 0, sizeof(t));
196  strptime("09:41:53", "%T", &t);
197  strftime(buf, sizeof(buf), "%H:%M:%S", &t);
198  EXPECT_STREQ("09:41:53", buf);
199}
200
201void SetTime(timer_t t, time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
202  itimerspec ts;
203  ts.it_value.tv_sec = value_s;
204  ts.it_value.tv_nsec = value_ns;
205  ts.it_interval.tv_sec = interval_s;
206  ts.it_interval.tv_nsec = interval_ns;
207  ASSERT_EQ(0, timer_settime(t, 0, &ts, NULL));
208}
209
210static void NoOpNotifyFunction(sigval_t) {
211}
212
213TEST(time, timer_create) {
214  sigevent_t se;
215  memset(&se, 0, sizeof(se));
216  se.sigev_notify = SIGEV_THREAD;
217  se.sigev_notify_function = NoOpNotifyFunction;
218  timer_t timer_id;
219  ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
220
221  int pid = fork();
222  ASSERT_NE(-1, pid) << strerror(errno);
223
224  if (pid == 0) {
225    // Timers are not inherited by the child.
226    ASSERT_EQ(-1, timer_delete(timer_id));
227    ASSERT_EQ(EINVAL, errno);
228    _exit(0);
229  }
230
231  int status;
232  ASSERT_EQ(pid, waitpid(pid, &status, 0));
233  ASSERT_TRUE(WIFEXITED(status));
234  ASSERT_EQ(0, WEXITSTATUS(status));
235
236  ASSERT_EQ(0, timer_delete(timer_id));
237}
238
239static int timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
240static void timer_create_SIGEV_SIGNAL_signal_handler(int signal_number) {
241  ++timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
242  ASSERT_EQ(SIGUSR1, signal_number);
243}
244
245TEST(time, timer_create_SIGEV_SIGNAL) {
246  sigevent_t se;
247  memset(&se, 0, sizeof(se));
248  se.sigev_notify = SIGEV_SIGNAL;
249  se.sigev_signo = SIGUSR1;
250
251  timer_t timer_id;
252  ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
253
254  timer_create_SIGEV_SIGNAL_signal_handler_invocation_count = 0;
255  ScopedSignalHandler ssh(SIGUSR1, timer_create_SIGEV_SIGNAL_signal_handler);
256
257  ASSERT_EQ(0, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
258
259  itimerspec ts;
260  ts.it_value.tv_sec =  0;
261  ts.it_value.tv_nsec = 1;
262  ts.it_interval.tv_sec = 0;
263  ts.it_interval.tv_nsec = 0;
264  ASSERT_EQ(0, timer_settime(timer_id, 0, &ts, NULL));
265
266  usleep(500000);
267  ASSERT_EQ(1, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
268}
269
270struct Counter {
271 private:
272  std::atomic<int> value;
273  timer_t timer_id;
274  sigevent_t se;
275  bool timer_valid;
276
277  void Create() {
278    ASSERT_FALSE(timer_valid);
279    ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &timer_id));
280    timer_valid = true;
281  }
282
283 public:
284  Counter(void (*fn)(sigval_t)) : value(0), timer_valid(false) {
285    memset(&se, 0, sizeof(se));
286    se.sigev_notify = SIGEV_THREAD;
287    se.sigev_notify_function = fn;
288    se.sigev_value.sival_ptr = this;
289    Create();
290  }
291  void DeleteTimer() {
292    ASSERT_TRUE(timer_valid);
293    ASSERT_EQ(0, timer_delete(timer_id));
294    timer_valid = false;
295  }
296
297  ~Counter() {
298    if (timer_valid) {
299      DeleteTimer();
300    }
301  }
302
303  int Value() const {
304    return value;
305  }
306
307  void SetTime(time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
308    ::SetTime(timer_id, value_s, value_ns, interval_s, interval_ns);
309  }
310
311  bool ValueUpdated() {
312    int current_value = value;
313    time_t start = time(NULL);
314    while (current_value == value && (time(NULL) - start) < 5) {
315    }
316    return current_value != value;
317  }
318
319  static void CountNotifyFunction(sigval_t value) {
320    Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
321    ++cd->value;
322  }
323
324  static void CountAndDisarmNotifyFunction(sigval_t value) {
325    Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
326    ++cd->value;
327
328    // Setting the initial expiration time to 0 disarms the timer.
329    cd->SetTime(0, 0, 1, 0);
330  }
331};
332
333TEST(time, timer_settime_0) {
334  Counter counter(Counter::CountAndDisarmNotifyFunction);
335  ASSERT_EQ(0, counter.Value());
336
337  counter.SetTime(0, 500000000, 1, 0);
338  sleep(1);
339
340  // The count should just be 1 because we disarmed the timer the first time it fired.
341  ASSERT_EQ(1, counter.Value());
342}
343
344TEST(time, timer_settime_repeats) {
345  Counter counter(Counter::CountNotifyFunction);
346  ASSERT_EQ(0, counter.Value());
347
348  counter.SetTime(0, 1, 0, 10);
349  ASSERT_TRUE(counter.ValueUpdated());
350  ASSERT_TRUE(counter.ValueUpdated());
351  ASSERT_TRUE(counter.ValueUpdated());
352  counter.DeleteTimer();
353  // Add a sleep as other threads may be calling the callback function when the timer is deleted.
354  usleep(500000);
355}
356
357static int timer_create_NULL_signal_handler_invocation_count;
358static void timer_create_NULL_signal_handler(int signal_number) {
359  ++timer_create_NULL_signal_handler_invocation_count;
360  ASSERT_EQ(SIGALRM, signal_number);
361}
362
363TEST(time, timer_create_NULL) {
364  // A NULL sigevent* is equivalent to asking for SIGEV_SIGNAL for SIGALRM.
365  timer_t timer_id;
366  ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id));
367
368  timer_create_NULL_signal_handler_invocation_count = 0;
369  ScopedSignalHandler ssh(SIGALRM, timer_create_NULL_signal_handler);
370
371  ASSERT_EQ(0, timer_create_NULL_signal_handler_invocation_count);
372
373  SetTime(timer_id, 0, 1, 0, 0);
374  usleep(500000);
375
376  ASSERT_EQ(1, timer_create_NULL_signal_handler_invocation_count);
377}
378
379TEST(time, timer_create_EINVAL) {
380  clockid_t invalid_clock = 16;
381
382  // A SIGEV_SIGNAL timer is easy; the kernel does all that.
383  timer_t timer_id;
384  ASSERT_EQ(-1, timer_create(invalid_clock, NULL, &timer_id));
385  ASSERT_EQ(EINVAL, errno);
386
387  // A SIGEV_THREAD timer is more interesting because we have stuff to clean up.
388  sigevent_t se;
389  memset(&se, 0, sizeof(se));
390  se.sigev_notify = SIGEV_THREAD;
391  se.sigev_notify_function = NoOpNotifyFunction;
392  ASSERT_EQ(-1, timer_create(invalid_clock, &se, &timer_id));
393  ASSERT_EQ(EINVAL, errno);
394}
395
396TEST(time, timer_delete_multiple) {
397  timer_t timer_id;
398  ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id));
399  ASSERT_EQ(0, timer_delete(timer_id));
400  ASSERT_EQ(-1, timer_delete(timer_id));
401  ASSERT_EQ(EINVAL, errno);
402
403  sigevent_t se;
404  memset(&se, 0, sizeof(se));
405  se.sigev_notify = SIGEV_THREAD;
406  se.sigev_notify_function = NoOpNotifyFunction;
407  ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
408  ASSERT_EQ(0, timer_delete(timer_id));
409  ASSERT_EQ(-1, timer_delete(timer_id));
410  ASSERT_EQ(EINVAL, errno);
411}
412
413TEST(time, timer_create_multiple) {
414  Counter counter1(Counter::CountNotifyFunction);
415  Counter counter2(Counter::CountNotifyFunction);
416  Counter counter3(Counter::CountNotifyFunction);
417
418  ASSERT_EQ(0, counter1.Value());
419  ASSERT_EQ(0, counter2.Value());
420  ASSERT_EQ(0, counter3.Value());
421
422  counter2.SetTime(0, 500000000, 0, 0);
423  sleep(1);
424
425  EXPECT_EQ(0, counter1.Value());
426  EXPECT_EQ(1, counter2.Value());
427  EXPECT_EQ(0, counter3.Value());
428}
429
430// Test to verify that disarming a repeatable timer disables the callbacks.
431TEST(time, timer_disarm_terminates) {
432  Counter counter(Counter::CountNotifyFunction);
433  ASSERT_EQ(0, counter.Value());
434
435  counter.SetTime(0, 1, 0, 1);
436  ASSERT_TRUE(counter.ValueUpdated());
437  ASSERT_TRUE(counter.ValueUpdated());
438  ASSERT_TRUE(counter.ValueUpdated());
439
440  counter.SetTime(0, 0, 0, 0);
441  // Add a sleep as the kernel may have pending events when the timer is disarmed.
442  usleep(500000);
443  int value = counter.Value();
444  usleep(500000);
445
446  // Verify the counter has not been incremented.
447  ASSERT_EQ(value, counter.Value());
448}
449
450// Test to verify that deleting a repeatable timer disables the callbacks.
451TEST(time, timer_delete_terminates) {
452  Counter counter(Counter::CountNotifyFunction);
453  ASSERT_EQ(0, counter.Value());
454
455  counter.SetTime(0, 1, 0, 1);
456  ASSERT_TRUE(counter.ValueUpdated());
457  ASSERT_TRUE(counter.ValueUpdated());
458  ASSERT_TRUE(counter.ValueUpdated());
459
460  counter.DeleteTimer();
461  // Add a sleep as other threads may be calling the callback function when the timer is deleted.
462  usleep(500000);
463  int value = counter.Value();
464  usleep(500000);
465
466  // Verify the counter has not been incremented.
467  ASSERT_EQ(value, counter.Value());
468}
469
470struct TimerDeleteData {
471  timer_t timer_id;
472  pthread_t thread_id;
473  volatile bool complete;
474};
475
476static void TimerDeleteCallback(sigval_t value) {
477  TimerDeleteData* tdd = reinterpret_cast<TimerDeleteData*>(value.sival_ptr);
478
479  tdd->thread_id = pthread_self();
480  timer_delete(tdd->timer_id);
481  tdd->complete = true;
482}
483
484TEST(time, timer_delete_from_timer_thread) {
485  TimerDeleteData tdd;
486  sigevent_t se;
487
488  memset(&se, 0, sizeof(se));
489  se.sigev_notify = SIGEV_THREAD;
490  se.sigev_notify_function = TimerDeleteCallback;
491  se.sigev_value.sival_ptr = &tdd;
492
493  tdd.complete = false;
494  ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &tdd.timer_id));
495
496  itimerspec ts;
497  ts.it_value.tv_sec = 1;
498  ts.it_value.tv_nsec = 0;
499  ts.it_interval.tv_sec = 0;
500  ts.it_interval.tv_nsec = 0;
501  ASSERT_EQ(0, timer_settime(tdd.timer_id, 0, &ts, NULL));
502
503  time_t cur_time = time(NULL);
504  while (!tdd.complete && (time(NULL) - cur_time) < 5);
505  ASSERT_TRUE(tdd.complete);
506
507#if defined(__BIONIC__)
508  // Since bionic timers are implemented by creating a thread to handle the
509  // callback, verify that the thread actually completes.
510  cur_time = time(NULL);
511  while (pthread_detach(tdd.thread_id) != ESRCH && (time(NULL) - cur_time) < 5);
512  ASSERT_EQ(ESRCH, pthread_detach(tdd.thread_id));
513#endif
514}
515
516TEST(time, clock_gettime) {
517  // Try to ensure that our vdso clock_gettime is working.
518  timespec ts1;
519  ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts1));
520  timespec ts2;
521  ASSERT_EQ(0, syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts2));
522
523  // What's the difference between the two?
524  ts2.tv_sec -= ts1.tv_sec;
525  ts2.tv_nsec -= ts1.tv_nsec;
526  if (ts2.tv_nsec < 0) {
527    --ts2.tv_sec;
528    ts2.tv_nsec += NS_PER_S;
529  }
530
531  // Should be less than (a very generous, to try to avoid flakiness) 1000000ns.
532  ASSERT_EQ(0, ts2.tv_sec);
533  ASSERT_LT(ts2.tv_nsec, 1000000);
534}
535
536TEST(time, clock) {
537  // clock(3) is hard to test, but a 1s sleep should cost less than 1ms.
538  clock_t t0 = clock();
539  sleep(1);
540  clock_t t1 = clock();
541  ASSERT_LT(t1 - t0, CLOCKS_PER_SEC / 1000);
542}
543
544pid_t GetInvalidPid() {
545  FILE* fp = fopen("/proc/sys/kernel/pid_max", "r");
546  long pid_max;
547  fscanf(fp, "%ld", &pid_max);
548  pid_t invalid_pid = static_cast<pid_t>(pid_max + 1);
549  fclose(fp);
550  return invalid_pid;
551}
552
553TEST(time, clock_getcpuclockid) {
554  // For current process.
555  clockid_t clockid;
556  ASSERT_EQ(0, clock_getcpuclockid(getpid(), &clockid));
557
558  timespec ts;
559  ASSERT_EQ(0, clock_gettime(clockid, &ts));
560
561  // For parent process.
562  ASSERT_EQ(0, clock_getcpuclockid(getppid(), &clockid));
563  ASSERT_EQ(0, clock_gettime(clockid, &ts));
564
565  // For invalid process.
566  // We can't use -1 for invalid pid here, because clock_getcpuclockid() can't detect it.
567  errno = 0;
568  ASSERT_EQ(ESRCH, clock_getcpuclockid(GetInvalidPid(), &clockid));
569  ASSERT_EQ(0, errno);
570}
571
572TEST(time, clock_settime) {
573  errno = 0;
574  timespec ts;
575  ASSERT_EQ(-1, clock_settime(-1, &ts));
576  ASSERT_EQ(EINVAL, errno);
577}
578
579TEST(time, clock_nanosleep) {
580  timespec in;
581  timespec out;
582  ASSERT_EQ(EINVAL, clock_nanosleep(-1, 0, &in, &out));
583}
584