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