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