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