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