OSDN Git Service

Merge "Split up the stack space tests into their own noinline functions."
[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 <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 #include "utils.h"
31
32 #include "private/bionic_constants.h"
33
34 TEST(time, gmtime) {
35   time_t t = 0;
36   tm* broken_down = gmtime(&t);
37   ASSERT_TRUE(broken_down != NULL);
38   ASSERT_EQ(0, broken_down->tm_sec);
39   ASSERT_EQ(0, broken_down->tm_min);
40   ASSERT_EQ(0, broken_down->tm_hour);
41   ASSERT_EQ(1, broken_down->tm_mday);
42   ASSERT_EQ(0, broken_down->tm_mon);
43   ASSERT_EQ(1970, broken_down->tm_year + 1900);
44 }
45
46 static void* gmtime_no_stack_overflow_14313703_fn(void*) {
47   const char* original_tz = getenv("TZ");
48   // Ensure we'll actually have to enter tzload by using a time zone that doesn't exist.
49   setenv("TZ", "gmtime_stack_overflow_14313703", 1);
50   tzset();
51   if (original_tz != NULL) {
52     setenv("TZ", original_tz, 1);
53   }
54   tzset();
55   return NULL;
56 }
57
58 TEST(time, gmtime_no_stack_overflow_14313703) {
59   // Is it safe to call tzload on a thread with a small stack?
60   // http://b/14313703
61   // https://code.google.com/p/android/issues/detail?id=61130
62   pthread_attr_t a;
63   ASSERT_EQ(0, pthread_attr_init(&a));
64   ASSERT_EQ(0, pthread_attr_setstacksize(&a, PTHREAD_STACK_MIN));
65
66   pthread_t t;
67   ASSERT_EQ(0, pthread_create(&t, &a, gmtime_no_stack_overflow_14313703_fn, NULL));
68   ASSERT_EQ(0, pthread_join(t, nullptr));
69 }
70
71 TEST(time, mktime_empty_TZ) {
72   // tzcode used to have a bug where it didn't reinitialize some internal state.
73
74   // Choose a time where DST is set.
75   struct tm t;
76   memset(&t, 0, sizeof(tm));
77   t.tm_year = 1980 - 1900;
78   t.tm_mon = 6;
79   t.tm_mday = 2;
80
81   setenv("TZ", "America/Los_Angeles", 1);
82   tzset();
83   ASSERT_EQ(static_cast<time_t>(331372800U), mktime(&t));
84
85   memset(&t, 0, sizeof(tm));
86   t.tm_year = 1980 - 1900;
87   t.tm_mon = 6;
88   t.tm_mday = 2;
89
90   setenv("TZ", "", 1); // Implies UTC.
91   tzset();
92   ASSERT_EQ(static_cast<time_t>(331344000U), mktime(&t));
93 }
94
95 TEST(time, mktime_10310929) {
96   struct tm t;
97   memset(&t, 0, sizeof(tm));
98   t.tm_year = 200;
99   t.tm_mon = 2;
100   t.tm_mday = 10;
101
102 #if !defined(__LP64__)
103   // 32-bit bionic stupidly had a signed 32-bit time_t.
104   ASSERT_EQ(-1, mktime(&t));
105   ASSERT_EQ(EOVERFLOW, errno);
106 #else
107   // Everyone else should be using a signed 64-bit time_t.
108   ASSERT_GE(sizeof(time_t) * 8, 64U);
109
110   setenv("TZ", "America/Los_Angeles", 1);
111   tzset();
112   errno = 0;
113   ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&t));
114   ASSERT_EQ(0, errno);
115
116   setenv("TZ", "UTC", 1);
117   tzset();
118   errno = 0;
119   ASSERT_EQ(static_cast<time_t>(4108320000U), mktime(&t));
120   ASSERT_EQ(0, errno);
121 #endif
122 }
123
124 TEST(time, mktime_EOVERFLOW) {
125   struct tm t;
126   memset(&t, 0, sizeof(tm));
127
128   // LP32 year range is 1901-2038, so this year is guaranteed not to overflow.
129   t.tm_year = 2016 - 1900;
130
131   t.tm_mon = 2;
132   t.tm_mday = 10;
133
134   errno = 0;
135   ASSERT_NE(static_cast<time_t>(-1), mktime(&t));
136   ASSERT_EQ(0, errno);
137
138   // This will overflow for LP32 or LP64.
139   t.tm_year = INT_MAX;
140
141   errno = 0;
142   ASSERT_EQ(static_cast<time_t>(-1), mktime(&t));
143   ASSERT_EQ(EOVERFLOW, errno);
144 }
145
146 TEST(time, strftime) {
147   setenv("TZ", "UTC", 1);
148
149   struct tm t;
150   memset(&t, 0, sizeof(tm));
151   t.tm_year = 200;
152   t.tm_mon = 2;
153   t.tm_mday = 10;
154
155   char buf[64];
156
157   // Seconds since the epoch.
158 #if defined(__BIONIC__) || defined(__LP64__) // Not 32-bit glibc.
159   EXPECT_EQ(10U, strftime(buf, sizeof(buf), "%s", &t));
160   EXPECT_STREQ("4108320000", buf);
161 #endif
162
163   // Date and time as text.
164   EXPECT_EQ(24U, strftime(buf, sizeof(buf), "%c", &t));
165   EXPECT_STREQ("Sun Mar 10 00:00:00 2100", buf);
166 }
167
168 TEST(time, strftime_null_tm_zone) {
169   // Netflix on Nexus Player wouldn't start (http://b/25170306).
170   struct tm t;
171   memset(&t, 0, sizeof(tm));
172
173   char buf[64];
174
175   setenv("TZ", "America/Los_Angeles", 1);
176   tzset();
177
178   t.tm_isdst = 0; // "0 if Daylight Savings Time is not in effect".
179   EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
180   EXPECT_STREQ("<PST>", buf);
181
182 #if defined(__BIONIC__) // glibc 2.19 only copes with tm_isdst being 0 and 1.
183   t.tm_isdst = 2; // "positive if Daylight Savings Time is in effect"
184   EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
185   EXPECT_STREQ("<PDT>", buf);
186
187   t.tm_isdst = -123; // "and negative if the information is not available".
188   EXPECT_EQ(2U, strftime(buf, sizeof(buf), "<%Z>", &t));
189   EXPECT_STREQ("<>", buf);
190 #endif
191
192   setenv("TZ", "UTC", 1);
193   tzset();
194
195   t.tm_isdst = 0;
196   EXPECT_EQ(5U, strftime(buf, sizeof(buf), "<%Z>", &t));
197   EXPECT_STREQ("<UTC>", buf);
198
199 #if defined(__BIONIC__) // glibc 2.19 thinks UTC DST is "UTC".
200   t.tm_isdst = 1; // UTC has no DST.
201   EXPECT_EQ(2U, strftime(buf, sizeof(buf), "<%Z>", &t));
202   EXPECT_STREQ("<>", buf);
203 #endif
204 }
205
206 TEST(time, strftime_l) {
207   locale_t cloc = newlocale(LC_ALL, "C.UTF-8", 0);
208   locale_t old_locale = uselocale(cloc);
209
210   setenv("TZ", "UTC", 1);
211
212   struct tm t;
213   memset(&t, 0, sizeof(tm));
214   t.tm_year = 200;
215   t.tm_mon = 2;
216   t.tm_mday = 10;
217
218   // Date and time as text.
219   char buf[64];
220   EXPECT_EQ(24U, strftime_l(buf, sizeof(buf), "%c", &t, cloc));
221   EXPECT_STREQ("Sun Mar 10 00:00:00 2100", buf);
222
223   uselocale(old_locale);
224   freelocale(cloc);
225 }
226
227 TEST(time, strptime) {
228   setenv("TZ", "UTC", 1);
229
230   struct tm t;
231   char buf[64];
232
233   memset(&t, 0, sizeof(t));
234   strptime("11:14", "%R", &t);
235   strftime(buf, sizeof(buf), "%H:%M", &t);
236   EXPECT_STREQ("11:14", buf);
237
238   memset(&t, 0, sizeof(t));
239   strptime("09:41:53", "%T", &t);
240   strftime(buf, sizeof(buf), "%H:%M:%S", &t);
241   EXPECT_STREQ("09:41:53", buf);
242 }
243
244 void SetTime(timer_t t, time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
245   itimerspec ts;
246   ts.it_value.tv_sec = value_s;
247   ts.it_value.tv_nsec = value_ns;
248   ts.it_interval.tv_sec = interval_s;
249   ts.it_interval.tv_nsec = interval_ns;
250   ASSERT_EQ(0, timer_settime(t, 0, &ts, NULL));
251 }
252
253 static void NoOpNotifyFunction(sigval_t) {
254 }
255
256 TEST(time, timer_create) {
257   sigevent_t se;
258   memset(&se, 0, sizeof(se));
259   se.sigev_notify = SIGEV_THREAD;
260   se.sigev_notify_function = NoOpNotifyFunction;
261   timer_t timer_id;
262   ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
263
264   pid_t pid = fork();
265   ASSERT_NE(-1, pid) << strerror(errno);
266
267   if (pid == 0) {
268     // Timers are not inherited by the child.
269     ASSERT_EQ(-1, timer_delete(timer_id));
270     ASSERT_EQ(EINVAL, errno);
271     _exit(0);
272   }
273
274   AssertChildExited(pid, 0);
275
276   ASSERT_EQ(0, timer_delete(timer_id));
277 }
278
279 static int timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
280 static void timer_create_SIGEV_SIGNAL_signal_handler(int signal_number) {
281   ++timer_create_SIGEV_SIGNAL_signal_handler_invocation_count;
282   ASSERT_EQ(SIGUSR1, signal_number);
283 }
284
285 TEST(time, timer_create_SIGEV_SIGNAL) {
286   sigevent_t se;
287   memset(&se, 0, sizeof(se));
288   se.sigev_notify = SIGEV_SIGNAL;
289   se.sigev_signo = SIGUSR1;
290
291   timer_t timer_id;
292   ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
293
294   timer_create_SIGEV_SIGNAL_signal_handler_invocation_count = 0;
295   ScopedSignalHandler ssh(SIGUSR1, timer_create_SIGEV_SIGNAL_signal_handler);
296
297   ASSERT_EQ(0, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
298
299   itimerspec ts;
300   ts.it_value.tv_sec =  0;
301   ts.it_value.tv_nsec = 1;
302   ts.it_interval.tv_sec = 0;
303   ts.it_interval.tv_nsec = 0;
304   ASSERT_EQ(0, timer_settime(timer_id, 0, &ts, NULL));
305
306   usleep(500000);
307   ASSERT_EQ(1, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count);
308 }
309
310 struct Counter {
311  private:
312   std::atomic<int> value;
313   timer_t timer_id;
314   sigevent_t se;
315   bool timer_valid;
316
317   void Create() {
318     ASSERT_FALSE(timer_valid);
319     ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &timer_id));
320     timer_valid = true;
321   }
322
323  public:
324   explicit Counter(void (*fn)(sigval_t)) : value(0), timer_valid(false) {
325     memset(&se, 0, sizeof(se));
326     se.sigev_notify = SIGEV_THREAD;
327     se.sigev_notify_function = fn;
328     se.sigev_value.sival_ptr = this;
329     Create();
330   }
331   void DeleteTimer() {
332     ASSERT_TRUE(timer_valid);
333     ASSERT_EQ(0, timer_delete(timer_id));
334     timer_valid = false;
335   }
336
337   ~Counter() {
338     if (timer_valid) {
339       DeleteTimer();
340     }
341   }
342
343   int Value() const {
344     return value;
345   }
346
347   void SetTime(time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
348     ::SetTime(timer_id, value_s, value_ns, interval_s, interval_ns);
349   }
350
351   bool ValueUpdated() {
352     int current_value = value;
353     time_t start = time(NULL);
354     while (current_value == value && (time(NULL) - start) < 5) {
355     }
356     return current_value != value;
357   }
358
359   static void CountNotifyFunction(sigval_t value) {
360     Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
361     ++cd->value;
362   }
363
364   static void CountAndDisarmNotifyFunction(sigval_t value) {
365     Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr);
366     ++cd->value;
367
368     // Setting the initial expiration time to 0 disarms the timer.
369     cd->SetTime(0, 0, 1, 0);
370   }
371 };
372
373 TEST(time, timer_settime_0) {
374   Counter counter(Counter::CountAndDisarmNotifyFunction);
375   ASSERT_EQ(0, counter.Value());
376
377   counter.SetTime(0, 500000000, 1, 0);
378   sleep(1);
379
380   // The count should just be 1 because we disarmed the timer the first time it fired.
381   ASSERT_EQ(1, counter.Value());
382 }
383
384 TEST(time, timer_settime_repeats) {
385   Counter counter(Counter::CountNotifyFunction);
386   ASSERT_EQ(0, counter.Value());
387
388   counter.SetTime(0, 1, 0, 10);
389   ASSERT_TRUE(counter.ValueUpdated());
390   ASSERT_TRUE(counter.ValueUpdated());
391   ASSERT_TRUE(counter.ValueUpdated());
392   counter.DeleteTimer();
393   // Add a sleep as other threads may be calling the callback function when the timer is deleted.
394   usleep(500000);
395 }
396
397 static int timer_create_NULL_signal_handler_invocation_count;
398 static void timer_create_NULL_signal_handler(int signal_number) {
399   ++timer_create_NULL_signal_handler_invocation_count;
400   ASSERT_EQ(SIGALRM, signal_number);
401 }
402
403 TEST(time, timer_create_NULL) {
404   // A NULL sigevent* is equivalent to asking for SIGEV_SIGNAL for SIGALRM.
405   timer_t timer_id;
406   ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id));
407
408   timer_create_NULL_signal_handler_invocation_count = 0;
409   ScopedSignalHandler ssh(SIGALRM, timer_create_NULL_signal_handler);
410
411   ASSERT_EQ(0, timer_create_NULL_signal_handler_invocation_count);
412
413   SetTime(timer_id, 0, 1, 0, 0);
414   usleep(500000);
415
416   ASSERT_EQ(1, timer_create_NULL_signal_handler_invocation_count);
417 }
418
419 TEST(time, timer_create_EINVAL) {
420   clockid_t invalid_clock = 16;
421
422   // A SIGEV_SIGNAL timer is easy; the kernel does all that.
423   timer_t timer_id;
424   ASSERT_EQ(-1, timer_create(invalid_clock, NULL, &timer_id));
425   ASSERT_EQ(EINVAL, errno);
426
427   // A SIGEV_THREAD timer is more interesting because we have stuff to clean up.
428   sigevent_t se;
429   memset(&se, 0, sizeof(se));
430   se.sigev_notify = SIGEV_THREAD;
431   se.sigev_notify_function = NoOpNotifyFunction;
432   ASSERT_EQ(-1, timer_create(invalid_clock, &se, &timer_id));
433   ASSERT_EQ(EINVAL, errno);
434 }
435
436 TEST(time, timer_delete_multiple) {
437   timer_t timer_id;
438   ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id));
439   ASSERT_EQ(0, timer_delete(timer_id));
440   ASSERT_EQ(-1, timer_delete(timer_id));
441   ASSERT_EQ(EINVAL, errno);
442
443   sigevent_t se;
444   memset(&se, 0, sizeof(se));
445   se.sigev_notify = SIGEV_THREAD;
446   se.sigev_notify_function = NoOpNotifyFunction;
447   ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id));
448   ASSERT_EQ(0, timer_delete(timer_id));
449   ASSERT_EQ(-1, timer_delete(timer_id));
450   ASSERT_EQ(EINVAL, errno);
451 }
452
453 TEST(time, timer_create_multiple) {
454   Counter counter1(Counter::CountNotifyFunction);
455   Counter counter2(Counter::CountNotifyFunction);
456   Counter counter3(Counter::CountNotifyFunction);
457
458   ASSERT_EQ(0, counter1.Value());
459   ASSERT_EQ(0, counter2.Value());
460   ASSERT_EQ(0, counter3.Value());
461
462   counter2.SetTime(0, 500000000, 0, 0);
463   sleep(1);
464
465   EXPECT_EQ(0, counter1.Value());
466   EXPECT_EQ(1, counter2.Value());
467   EXPECT_EQ(0, counter3.Value());
468 }
469
470 // Test to verify that disarming a repeatable timer disables the callbacks.
471 TEST(time, timer_disarm_terminates) {
472   Counter counter(Counter::CountNotifyFunction);
473   ASSERT_EQ(0, counter.Value());
474
475   counter.SetTime(0, 1, 0, 1);
476   ASSERT_TRUE(counter.ValueUpdated());
477   ASSERT_TRUE(counter.ValueUpdated());
478   ASSERT_TRUE(counter.ValueUpdated());
479
480   counter.SetTime(0, 0, 0, 0);
481   // Add a sleep as the kernel may have pending events when the timer is disarmed.
482   usleep(500000);
483   int value = counter.Value();
484   usleep(500000);
485
486   // Verify the counter has not been incremented.
487   ASSERT_EQ(value, counter.Value());
488 }
489
490 // Test to verify that deleting a repeatable timer disables the callbacks.
491 TEST(time, timer_delete_terminates) {
492   Counter counter(Counter::CountNotifyFunction);
493   ASSERT_EQ(0, counter.Value());
494
495   counter.SetTime(0, 1, 0, 1);
496   ASSERT_TRUE(counter.ValueUpdated());
497   ASSERT_TRUE(counter.ValueUpdated());
498   ASSERT_TRUE(counter.ValueUpdated());
499
500   counter.DeleteTimer();
501   // Add a sleep as other threads may be calling the callback function when the timer is deleted.
502   usleep(500000);
503   int value = counter.Value();
504   usleep(500000);
505
506   // Verify the counter has not been incremented.
507   ASSERT_EQ(value, counter.Value());
508 }
509
510 struct TimerDeleteData {
511   timer_t timer_id;
512   pid_t tid;
513   volatile bool complete;
514 };
515
516 static void TimerDeleteCallback(sigval_t value) {
517   TimerDeleteData* tdd = reinterpret_cast<TimerDeleteData*>(value.sival_ptr);
518
519   tdd->tid = gettid();
520   timer_delete(tdd->timer_id);
521   tdd->complete = true;
522 }
523
524 TEST(time, timer_delete_from_timer_thread) {
525   TimerDeleteData tdd;
526   sigevent_t se;
527
528   memset(&se, 0, sizeof(se));
529   se.sigev_notify = SIGEV_THREAD;
530   se.sigev_notify_function = TimerDeleteCallback;
531   se.sigev_value.sival_ptr = &tdd;
532
533   tdd.complete = false;
534   ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &tdd.timer_id));
535
536   itimerspec ts;
537   ts.it_value.tv_sec = 1;
538   ts.it_value.tv_nsec = 0;
539   ts.it_interval.tv_sec = 0;
540   ts.it_interval.tv_nsec = 0;
541   ASSERT_EQ(0, timer_settime(tdd.timer_id, 0, &ts, NULL));
542
543   time_t cur_time = time(NULL);
544   while (!tdd.complete && (time(NULL) - cur_time) < 5);
545   ASSERT_TRUE(tdd.complete);
546
547 #if defined(__BIONIC__)
548   // Since bionic timers are implemented by creating a thread to handle the
549   // callback, verify that the thread actually completes.
550   cur_time = time(NULL);
551   while ((kill(tdd.tid, 0) != -1 || errno != ESRCH) && (time(NULL) - cur_time) < 5);
552   ASSERT_EQ(-1, kill(tdd.tid, 0));
553   ASSERT_EQ(ESRCH, errno);
554 #endif
555 }
556
557 TEST(time, clock_gettime) {
558   // Try to ensure that our vdso clock_gettime is working.
559   timespec ts1;
560   ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts1));
561   timespec ts2;
562   ASSERT_EQ(0, syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts2));
563
564   // What's the difference between the two?
565   ts2.tv_sec -= ts1.tv_sec;
566   ts2.tv_nsec -= ts1.tv_nsec;
567   if (ts2.tv_nsec < 0) {
568     --ts2.tv_sec;
569     ts2.tv_nsec += NS_PER_S;
570   }
571
572   // Should be less than (a very generous, to try to avoid flakiness) 1000000ns.
573   ASSERT_EQ(0, ts2.tv_sec);
574   ASSERT_LT(ts2.tv_nsec, 1000000);
575 }
576
577 TEST(time, clock) {
578   // clock(3) is hard to test, but a 1s sleep should cost less than 1ms.
579   clock_t t0 = clock();
580   sleep(1);
581   clock_t t1 = clock();
582   ASSERT_LT(t1 - t0, CLOCKS_PER_SEC / 1000);
583 }
584
585 pid_t GetInvalidPid() {
586   FILE* fp = fopen("/proc/sys/kernel/pid_max", "r");
587   long pid_max;
588   fscanf(fp, "%ld", &pid_max);
589   pid_t invalid_pid = static_cast<pid_t>(pid_max + 1);
590   fclose(fp);
591   return invalid_pid;
592 }
593
594 TEST(time, clock_getcpuclockid) {
595   // For current process.
596   clockid_t clockid;
597   ASSERT_EQ(0, clock_getcpuclockid(getpid(), &clockid));
598
599   timespec ts;
600   ASSERT_EQ(0, clock_gettime(clockid, &ts));
601
602   // For parent process.
603   ASSERT_EQ(0, clock_getcpuclockid(getppid(), &clockid));
604   ASSERT_EQ(0, clock_gettime(clockid, &ts));
605
606   // For invalid process.
607   // We can't use -1 for invalid pid here, because clock_getcpuclockid() can't detect it.
608   errno = 0;
609   ASSERT_EQ(ESRCH, clock_getcpuclockid(GetInvalidPid(), &clockid));
610   ASSERT_EQ(0, errno);
611 }
612
613 TEST(time, clock_settime) {
614   errno = 0;
615   timespec ts;
616   ASSERT_EQ(-1, clock_settime(-1, &ts));
617   ASSERT_EQ(EINVAL, errno);
618 }
619
620 TEST(time, clock_nanosleep) {
621   timespec in;
622   timespec out;
623   ASSERT_EQ(EINVAL, clock_nanosleep(-1, 0, &in, &out));
624 }
625
626 TEST(time, clock_nanosleep_thread_cputime_id) {
627   timespec in;
628   in.tv_sec = 1;
629   in.tv_nsec = 0;
630   ASSERT_EQ(EINVAL, clock_nanosleep(CLOCK_THREAD_CPUTIME_ID, 0, &in, nullptr));
631 }
632
633 TEST(time, bug_31938693) {
634   // User-visible symptoms in N:
635   // http://b/31938693
636   // https://code.google.com/p/android/issues/detail?id=225132
637
638   // Actual underlying bug (the code change, not the tzdata upgrade that first exposed the bug):
639   // http://b/31848040
640
641   // This isn't a great test, because very few time zones were actually affected, and there's
642   // no real logic to which ones were affected: it was just a coincidence of the data that came
643   // after them in the tzdata file.
644
645   time_t t = 1475619727;
646   struct tm tm;
647
648   setenv("TZ", "America/Los_Angeles", 1);
649   tzset();
650   ASSERT_TRUE(localtime_r(&t, &tm) != nullptr);
651   EXPECT_EQ(15, tm.tm_hour);
652
653   setenv("TZ", "Europe/London", 1);
654   tzset();
655   ASSERT_TRUE(localtime_r(&t, &tm) != nullptr);
656   EXPECT_EQ(23, tm.tm_hour);
657
658   setenv("TZ", "America/Atka", 1);
659   tzset();
660   ASSERT_TRUE(localtime_r(&t, &tm) != nullptr);
661   EXPECT_EQ(13, tm.tm_hour);
662
663   setenv("TZ", "Pacific/Apia", 1);
664   tzset();
665   ASSERT_TRUE(localtime_r(&t, &tm) != nullptr);
666   EXPECT_EQ(12, tm.tm_hour);
667
668   setenv("TZ", "Pacific/Honolulu", 1);
669   tzset();
670   ASSERT_TRUE(localtime_r(&t, &tm) != nullptr);
671   EXPECT_EQ(12, tm.tm_hour);
672
673   setenv("TZ", "Asia/Magadan", 1);
674   tzset();
675   ASSERT_TRUE(localtime_r(&t, &tm) != nullptr);
676   EXPECT_EQ(9, tm.tm_hour);
677 }
678
679 TEST(time, bug_31339449) {
680   // POSIX says localtime acts as if it calls tzset.
681   // tzset does two things:
682   //  1. it sets the time zone ctime/localtime/mktime/strftime will use.
683   //  2. it sets the global `tzname`.
684   // POSIX says localtime_r need not set `tzname` (2).
685   // Q: should localtime_r set the time zone (1)?
686   // Upstream tzcode (and glibc) answer "no", everyone else answers "yes".
687
688   // Pick a time, any time...
689   time_t t = 1475619727;
690
691   // Call tzset with a specific timezone.
692   setenv("TZ", "America/Atka", 1);
693   tzset();
694
695   // If we change the timezone and call localtime, localtime should use the new timezone.
696   setenv("TZ", "America/Los_Angeles", 1);
697   struct tm* tm_p = localtime(&t);
698   EXPECT_EQ(15, tm_p->tm_hour);
699
700   // Reset the timezone back.
701   setenv("TZ", "America/Atka", 1);
702   tzset();
703
704 #if defined(__BIONIC__)
705   // If we change the timezone again and call localtime_r, localtime_r should use the new timezone.
706   setenv("TZ", "America/Los_Angeles", 1);
707   struct tm tm = {};
708   localtime_r(&t, &tm);
709   EXPECT_EQ(15, tm.tm_hour);
710 #else
711   // The BSDs agree with us, but glibc gets this wrong.
712 #endif
713 }