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