time_test.cpp revision d1ade7ce0237089d0e44eb2bee0691e4814d1289
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, strptime) {
147  setenv("TZ", "UTC", 1);
148
149  struct tm t;
150  char buf[64];
151
152  memset(&t, 0, sizeof(t));
153  strptime("11:14", "%R", &t);
154  strftime(buf, sizeof(buf), "%H:%M", &t);
155  EXPECT_STREQ("11:14", buf);
156
157  memset(&t, 0, sizeof(t));
158  strptime("09:41:53", "%T", &t);
159  strftime(buf, sizeof(buf), "%H:%M:%S", &t);
160  EXPECT_STREQ("09:41:53", buf);
161}
162
163void SetTime(timer_t t, time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
164  itimerspec ts;
165  ts.it_value.tv_sec = value_s;
166  ts.it_value.tv_nsec = value_ns;
167  ts.it_interval.tv_sec = interval_s;
168  ts.it_interval.tv_nsec = interval_ns;
169  ASSERT_EQ(0, timer_settime(t, 0, &ts, NULL));
170}
171
172static void NoOpNotifyFunction(sigval_t) {
173}
174
175TEST(time, timer_create) {
176  sigevent_t se;
177  memset(&se, 0, sizeof(se));
178  se.sigev_notify = SIGEV_THREAD;
179  se.sigev_notify_function = NoOpNotifyFunction;
180  timer_t timer_id;
181  ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
182
183  int pid = fork();
184  ASSERT_NE(-1, pid) << strerror(errno);
185
186  if (pid == 0) {
187    // Timers are not inherited by the child.
188    ASSERT_EQ(-1, timer_delete(timer_id));
189    ASSERT_EQ(EINVAL, errno);
190    _exit(0);
191  }
192
193  int status;
194  ASSERT_EQ(pid, waitpid(pid, &status, 0));
195  ASSERT_TRUE(WIFEXITED(status));
196  ASSERT_EQ(0, WEXITSTATUS(status));
197
198  ASSERT_EQ(0, timer_delete(timer_id));
199}
200
201static int timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
202static void timer_create_SIGEV_SIGNAL_signal_handler(int signal_number) {
203  ++timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
204  ASSERT_EQ(SIGUSR1, signal_number);
205}
206
207TEST(time, timer_create_SIGEV_SIGNAL) {
208  sigevent_t se;
209  memset(&se, 0, sizeof(se));
210  se.sigev_notify = SIGEV_SIGNAL;
211  se.sigev_signo = SIGUSR1;
212
213  timer_t timer_id;
214  ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
215
216  timer_create_SIGEV_SIGNAL_signal_handler_invocation_count = 0;
217  ScopedSignalHandler ssh(SIGUSR1, timer_create_SIGEV_SIGNAL_signal_handler);
218
219  ASSERT_EQ(0, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
220
221  itimerspec ts;
222  ts.it_value.tv_sec =  0;
223  ts.it_value.tv_nsec = 1;
224  ts.it_interval.tv_sec = 0;
225  ts.it_interval.tv_nsec = 0;
226  ASSERT_EQ(0, timer_settime(timer_id, 0, &ts, NULL));
227
228  usleep(500000);
229  ASSERT_EQ(1, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
230}
231
232struct Counter {
233 private:
234  std::atomic<int> value;
235  timer_t timer_id;
236  sigevent_t se;
237  bool timer_valid;
238
239  void Create() {
240    ASSERT_FALSE(timer_valid);
241    ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &timer_id));
242    timer_valid = true;
243  }
244
245 public:
246  Counter(void (*fn)(sigval_t)) : value(0), timer_valid(false) {
247    memset(&se, 0, sizeof(se));
248    se.sigev_notify = SIGEV_THREAD;
249    se.sigev_notify_function = fn;
250    se.sigev_value.sival_ptr = this;
251    Create();
252  }
253  void DeleteTimer() {
254    ASSERT_TRUE(timer_valid);
255    ASSERT_EQ(0, timer_delete(timer_id));
256    timer_valid = false;
257  }
258
259  ~Counter() {
260    if (timer_valid) {
261      DeleteTimer();
262    }
263  }
264
265  int Value() const {
266    return value;
267  }
268
269  void SetTime(time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
270    ::SetTime(timer_id, value_s, value_ns, interval_s, interval_ns);
271  }
272
273  bool ValueUpdated() {
274    int current_value = value;
275    time_t start = time(NULL);
276    while (current_value == value && (time(NULL) - start) < 5) {
277    }
278    return current_value != value;
279  }
280
281  static void CountNotifyFunction(sigval_t value) {
282    Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
283    ++cd->value;
284  }
285
286  static void CountAndDisarmNotifyFunction(sigval_t value) {
287    Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
288    ++cd->value;
289
290    // Setting the initial expiration time to 0 disarms the timer.
291    cd->SetTime(0, 0, 1, 0);
292  }
293};
294
295TEST(time, timer_settime_0) {
296  Counter counter(Counter::CountAndDisarmNotifyFunction);
297  ASSERT_EQ(0, counter.Value());
298
299  counter.SetTime(0, 1, 1, 0);
300  usleep(500000);
301
302  // The count should just be 1 because we disarmed the timer the first time it fired.
303  ASSERT_EQ(1, counter.Value());
304}
305
306TEST(time, timer_settime_repeats) {
307  Counter counter(Counter::CountNotifyFunction);
308  ASSERT_EQ(0, counter.Value());
309
310  counter.SetTime(0, 1, 0, 10);
311  ASSERT_TRUE(counter.ValueUpdated());
312  ASSERT_TRUE(counter.ValueUpdated());
313  ASSERT_TRUE(counter.ValueUpdated());
314  counter.DeleteTimer();
315  // Add a sleep as other threads may be calling the callback function when the timer is deleted.
316  usleep(500000);
317}
318
319static int timer_create_NULL_signal_handler_invocation_count;
320static void timer_create_NULL_signal_handler(int signal_number) {
321  ++timer_create_NULL_signal_handler_invocation_count;
322  ASSERT_EQ(SIGALRM, signal_number);
323}
324
325TEST(time, timer_create_NULL) {
326  // A NULL sigevent* is equivalent to asking for SIGEV_SIGNAL for SIGALRM.
327  timer_t timer_id;
328  ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id));
329
330  timer_create_NULL_signal_handler_invocation_count = 0;
331  ScopedSignalHandler ssh(SIGALRM, timer_create_NULL_signal_handler);
332
333  ASSERT_EQ(0, timer_create_NULL_signal_handler_invocation_count);
334
335  SetTime(timer_id, 0, 1, 0, 0);
336  usleep(500000);
337
338  ASSERT_EQ(1, timer_create_NULL_signal_handler_invocation_count);
339}
340
341TEST(time, timer_create_EINVAL) {
342  clockid_t invalid_clock = 16;
343
344  // A SIGEV_SIGNAL timer is easy; the kernel does all that.
345  timer_t timer_id;
346  ASSERT_EQ(-1, timer_create(invalid_clock, NULL, &timer_id));
347  ASSERT_EQ(EINVAL, errno);
348
349  // A SIGEV_THREAD timer is more interesting because we have stuff to clean up.
350  sigevent_t se;
351  memset(&se, 0, sizeof(se));
352  se.sigev_notify = SIGEV_THREAD;
353  se.sigev_notify_function = NoOpNotifyFunction;
354  ASSERT_EQ(-1, timer_create(invalid_clock, &se, &timer_id));
355  ASSERT_EQ(EINVAL, errno);
356}
357
358TEST(time, timer_delete_multiple) {
359  timer_t timer_id;
360  ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id));
361  ASSERT_EQ(0, timer_delete(timer_id));
362  ASSERT_EQ(-1, timer_delete(timer_id));
363  ASSERT_EQ(EINVAL, errno);
364
365  sigevent_t se;
366  memset(&se, 0, sizeof(se));
367  se.sigev_notify = SIGEV_THREAD;
368  se.sigev_notify_function = NoOpNotifyFunction;
369  ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
370  ASSERT_EQ(0, timer_delete(timer_id));
371  ASSERT_EQ(-1, timer_delete(timer_id));
372  ASSERT_EQ(EINVAL, errno);
373}
374
375TEST(time, timer_create_multiple) {
376  Counter counter1(Counter::CountNotifyFunction);
377  Counter counter2(Counter::CountNotifyFunction);
378  Counter counter3(Counter::CountNotifyFunction);
379
380  ASSERT_EQ(0, counter1.Value());
381  ASSERT_EQ(0, counter2.Value());
382  ASSERT_EQ(0, counter3.Value());
383
384  counter2.SetTime(0, 1, 0, 0);
385  usleep(500000);
386
387  EXPECT_EQ(0, counter1.Value());
388  EXPECT_EQ(1, counter2.Value());
389  EXPECT_EQ(0, counter3.Value());
390}
391
392// Test to verify that disarming a repeatable timer disables the callbacks.
393TEST(time, timer_disarm_terminates) {
394  Counter counter(Counter::CountNotifyFunction);
395  ASSERT_EQ(0, counter.Value());
396
397  counter.SetTime(0, 1, 0, 1);
398  ASSERT_TRUE(counter.ValueUpdated());
399  ASSERT_TRUE(counter.ValueUpdated());
400  ASSERT_TRUE(counter.ValueUpdated());
401
402  counter.SetTime(0, 0, 0, 0);
403  // Add a sleep as the kernel may have pending events when the timer is disarmed.
404  usleep(500000);
405  int value = counter.Value();
406  usleep(500000);
407
408  // Verify the counter has not been incremented.
409  ASSERT_EQ(value, counter.Value());
410}
411
412// Test to verify that deleting a repeatable timer disables the callbacks.
413TEST(time, timer_delete_terminates) {
414  Counter counter(Counter::CountNotifyFunction);
415  ASSERT_EQ(0, counter.Value());
416
417  counter.SetTime(0, 1, 0, 1);
418  ASSERT_TRUE(counter.ValueUpdated());
419  ASSERT_TRUE(counter.ValueUpdated());
420  ASSERT_TRUE(counter.ValueUpdated());
421
422  counter.DeleteTimer();
423  // Add a sleep as other threads may be calling the callback function when the timer is deleted.
424  usleep(500000);
425  int value = counter.Value();
426  usleep(500000);
427
428  // Verify the counter has not been incremented.
429  ASSERT_EQ(value, counter.Value());
430}
431
432struct TimerDeleteData {
433  timer_t timer_id;
434  pthread_t thread_id;
435  volatile bool complete;
436};
437
438static void TimerDeleteCallback(sigval_t value) {
439  TimerDeleteData* tdd = reinterpret_cast<TimerDeleteData*>(value.sival_ptr);
440
441  tdd->thread_id = pthread_self();
442  timer_delete(tdd->timer_id);
443  tdd->complete = true;
444}
445
446TEST(time, timer_delete_from_timer_thread) {
447  TimerDeleteData tdd;
448  sigevent_t se;
449
450  memset(&se, 0, sizeof(se));
451  se.sigev_notify = SIGEV_THREAD;
452  se.sigev_notify_function = TimerDeleteCallback;
453  se.sigev_value.sival_ptr = &tdd;
454
455  tdd.complete = false;
456  ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &tdd.timer_id));
457
458  itimerspec ts;
459  ts.it_value.tv_sec = 1;
460  ts.it_value.tv_nsec = 0;
461  ts.it_interval.tv_sec = 0;
462  ts.it_interval.tv_nsec = 0;
463  ASSERT_EQ(0, timer_settime(tdd.timer_id, 0, &ts, NULL));
464
465  time_t cur_time = time(NULL);
466  while (!tdd.complete && (time(NULL) - cur_time) < 5);
467  ASSERT_TRUE(tdd.complete);
468
469#if defined(__BIONIC__)
470  // Since bionic timers are implemented by creating a thread to handle the
471  // callback, verify that the thread actually completes.
472  cur_time = time(NULL);
473  while (pthread_detach(tdd.thread_id) != ESRCH && (time(NULL) - cur_time) < 5);
474  ASSERT_EQ(ESRCH, pthread_detach(tdd.thread_id));
475#endif
476}
477
478TEST(time, clock_gettime) {
479  // Try to ensure that our vdso clock_gettime is working.
480  timespec ts1;
481  ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts1));
482  timespec ts2;
483  ASSERT_EQ(0, syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts2));
484
485  // What's the difference between the two?
486  ts2.tv_sec -= ts1.tv_sec;
487  ts2.tv_nsec -= ts1.tv_nsec;
488  if (ts2.tv_nsec < 0) {
489    --ts2.tv_sec;
490    ts2.tv_nsec += NS_PER_S;
491  }
492
493  // Should be less than (a very generous, to try to avoid flakiness) 1000000ns.
494  ASSERT_EQ(0, ts2.tv_sec);
495  ASSERT_LT(ts2.tv_nsec, 1000000);
496}
497
498TEST(time, clock) {
499  // clock(3) is hard to test, but a 1s sleep should cost less than 1ms.
500  clock_t t0 = clock();
501  sleep(1);
502  clock_t t1 = clock();
503  ASSERT_LT(t1 - t0, CLOCKS_PER_SEC / 1000);
504}
505
506pid_t GetInvalidPid() {
507  FILE* fp = fopen("/proc/sys/kernel/pid_max", "r");
508  long pid_max;
509  fscanf(fp, "%ld", &pid_max);
510  pid_t invalid_pid = static_cast<pid_t>(pid_max + 1);
511  fclose(fp);
512  return invalid_pid;
513}
514
515TEST(time, clock_getcpuclockid) {
516  // For current process.
517  clockid_t clockid;
518  ASSERT_EQ(0, clock_getcpuclockid(getpid(), &clockid));
519
520  timespec ts;
521  ASSERT_EQ(0, clock_gettime(clockid, &ts));
522
523  // For parent process.
524  ASSERT_EQ(0, clock_getcpuclockid(getppid(), &clockid));
525  ASSERT_EQ(0, clock_gettime(clockid, &ts));
526
527  // For invalid process.
528  // We can't use -1 for invalid pid here, because clock_getcpuclockid() can't detect it.
529  errno = 0;
530  ASSERT_EQ(ESRCH, clock_getcpuclockid(GetInvalidPid(), &clockid));
531  ASSERT_EQ(0, errno);
532}
533
534TEST(time, clock_settime) {
535  errno = 0;
536  timespec ts;
537  ASSERT_EQ(-1, clock_settime(-1, &ts));
538  ASSERT_EQ(EINVAL, errno);
539}
540
541TEST(time, clock_nanosleep) {
542  timespec in;
543  timespec out;
544  ASSERT_EQ(EINVAL, clock_nanosleep(-1, 0, &in, &out));
545}
546