time_test.cpp revision be1d91dedcfb346ced5ac496cd454f5b2e9bc4a9
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 <signal.h> 23#include <sys/types.h> 24#include <sys/wait.h> 25 26#include "ScopedSignalHandler.h" 27 28#if defined(__BIONIC__) // mktime_tz is a bionic extension. 29#include <libc/private/bionic_time.h> 30#endif // __BIONIC__ 31 32TEST(time, mktime_tz) { 33#if defined(__BIONIC__) 34 struct tm epoch; 35 memset(&epoch, 0, sizeof(tm)); 36 epoch.tm_year = 1970 - 1900; 37 epoch.tm_mon = 1; 38 epoch.tm_mday = 1; 39 40 // Alphabetically first. Coincidentally equivalent to UTC. 41 ASSERT_EQ(2678400, mktime_tz(&epoch, "Africa/Abidjan")); 42 43 // Alphabetically last. Coincidentally equivalent to UTC. 44 ASSERT_EQ(2678400, mktime_tz(&epoch, "Zulu")); 45 46 // Somewhere in the middle, not UTC. 47 ASSERT_EQ(2707200, mktime_tz(&epoch, "America/Los_Angeles")); 48 49 // Missing. Falls back to UTC. 50 ASSERT_EQ(2678400, mktime_tz(&epoch, "PST")); 51#else // __BIONIC__ 52 GTEST_LOG_(INFO) << "This test does nothing.\n"; 53#endif // __BIONIC__ 54} 55 56TEST(time, gmtime) { 57 time_t t = 0; 58 tm* broken_down = gmtime(&t); 59 ASSERT_TRUE(broken_down != NULL); 60 ASSERT_EQ(0, broken_down->tm_sec); 61 ASSERT_EQ(0, broken_down->tm_min); 62 ASSERT_EQ(0, broken_down->tm_hour); 63 ASSERT_EQ(1, broken_down->tm_mday); 64 ASSERT_EQ(0, broken_down->tm_mon); 65 ASSERT_EQ(1970, broken_down->tm_year + 1900); 66} 67 68TEST(time, mktime_10310929) { 69 struct tm t; 70 memset(&t, 0, sizeof(tm)); 71 t.tm_year = 200; 72 t.tm_mon = 2; 73 t.tm_mday = 10; 74 75#if !defined(__LP64__) 76 // 32-bit bionic stupidly had a signed 32-bit time_t. 77 ASSERT_EQ(-1, mktime(&t)); 78#if defined(__BIONIC__) 79 ASSERT_EQ(-1, mktime_tz(&t, "UTC")); 80#endif 81#else 82 // Everyone else should be using a signed 64-bit time_t. 83 ASSERT_GE(sizeof(time_t) * 8, 64U); 84 85 setenv("TZ", "America/Los_Angeles", 1); 86 tzset(); 87 ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&t)); 88#if defined(__BIONIC__) 89 ASSERT_EQ(static_cast<time_t>(4108320000U), mktime_tz(&t, "UTC")); 90#endif 91 92 setenv("TZ", "UTC", 1); 93 tzset(); 94 ASSERT_EQ(static_cast<time_t>(4108320000U), mktime(&t)); 95#if defined(__BIONIC__) 96 ASSERT_EQ(static_cast<time_t>(4108348800U), mktime_tz(&t, "America/Los_Angeles")); 97#endif 98#endif 99} 100 101void SetTime(timer_t t, time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) { 102 itimerspec ts; 103 ts.it_value.tv_sec = value_s; 104 ts.it_value.tv_nsec = value_ns; 105 ts.it_interval.tv_sec = interval_s; 106 ts.it_interval.tv_nsec = interval_ns; 107 ASSERT_EQ(0, timer_settime(t, TIMER_ABSTIME, &ts, NULL)); 108} 109 110static void NoOpNotifyFunction(sigval_t) { 111} 112 113TEST(time, timer_create) { 114 sigevent_t se; 115 memset(&se, 0, sizeof(se)); 116 se.sigev_notify = SIGEV_THREAD; 117 se.sigev_notify_function = NoOpNotifyFunction; 118 timer_t timer_id; 119 ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id)); 120 121 int pid = fork(); 122 ASSERT_NE(-1, pid) << strerror(errno); 123 124 if (pid == 0) { 125 // Timers are not inherited by the child. 126 ASSERT_EQ(-1, timer_delete(timer_id)); 127 ASSERT_EQ(EINVAL, errno); 128 _exit(0); 129 } 130 131 int status; 132 ASSERT_EQ(pid, waitpid(pid, &status, 0)); 133 ASSERT_TRUE(WIFEXITED(status)); 134 ASSERT_EQ(0, WEXITSTATUS(status)); 135 136 ASSERT_EQ(0, timer_delete(timer_id)); 137} 138 139static int timer_create_SIGEV_SIGNAL_signal_handler_invocation_count = 0; 140static void timer_create_SIGEV_SIGNAL_signal_handler(int signal_number) { 141 ++timer_create_SIGEV_SIGNAL_signal_handler_invocation_count; 142 ASSERT_EQ(SIGUSR1, signal_number); 143} 144 145TEST(time, timer_create_SIGEV_SIGNAL) { 146 sigevent_t se; 147 memset(&se, 0, sizeof(se)); 148 se.sigev_notify = SIGEV_SIGNAL; 149 se.sigev_signo = SIGUSR1; 150 151 timer_t timer_id; 152 ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id)); 153 154 ScopedSignalHandler ssh(SIGUSR1, timer_create_SIGEV_SIGNAL_signal_handler); 155 156 ASSERT_EQ(0, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count); 157 158 itimerspec ts; 159 ts.it_value.tv_sec = 0; 160 ts.it_value.tv_nsec = 1; 161 ts.it_interval.tv_sec = 0; 162 ts.it_interval.tv_nsec = 0; 163 ASSERT_EQ(0, timer_settime(timer_id, TIMER_ABSTIME, &ts, NULL)); 164 165 usleep(500000); 166 ASSERT_EQ(1, timer_create_SIGEV_SIGNAL_signal_handler_invocation_count); 167} 168 169struct Counter { 170 volatile int value; 171 timer_t timer_id; 172 sigevent_t se; 173 174 Counter(void (*fn)(sigval_t)) : value(0) { 175 memset(&se, 0, sizeof(se)); 176 se.sigev_notify = SIGEV_THREAD; 177 se.sigev_notify_function = fn; 178 se.sigev_value.sival_ptr = this; 179 } 180 181 void Create() { 182 ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &timer_id)); 183 } 184 185 ~Counter() { 186 if (timer_delete(timer_id) != 0) { 187 abort(); 188 } 189 } 190 191 static void CountNotifyFunction(sigval_t value) { 192 Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr); 193 ++cd->value; 194 } 195 196 static void CountAndDisarmNotifyFunction(sigval_t value) { 197 Counter* cd = reinterpret_cast<Counter*>(value.sival_ptr); 198 ++cd->value; 199 200 // Setting the initial expiration time to 0 disarms the timer. 201 SetTime(cd->timer_id, 0, 0, 1, 0); 202 } 203}; 204 205TEST(time, timer_settime_0) { 206 Counter counter(Counter::CountAndDisarmNotifyFunction); 207 counter.Create(); 208 209 ASSERT_EQ(0, counter.value); 210 211 SetTime(counter.timer_id, 0, 1, 1, 0); 212 usleep(500000); 213 214 // The count should just be 1 because we disarmed the timer the first time it fired. 215 ASSERT_EQ(1, counter.value); 216} 217 218TEST(time, timer_settime_repeats) { 219 Counter counter(Counter::CountNotifyFunction); 220 counter.Create(); 221 222 ASSERT_EQ(0, counter.value); 223 224 SetTime(counter.timer_id, 0, 1, 0, 10); 225 usleep(500000); 226 227 // The count should just be > 1 because we let the timer repeat. 228 ASSERT_GT(counter.value, 1); 229} 230 231static int timer_create_NULL_signal_handler_invocation_count = 0; 232static void timer_create_NULL_signal_handler(int signal_number) { 233 ++timer_create_NULL_signal_handler_invocation_count; 234 ASSERT_EQ(SIGALRM, signal_number); 235} 236 237TEST(time, timer_create_NULL) { 238 // A NULL sigevent* is equivalent to asking for SIGEV_SIGNAL for SIGALRM. 239 timer_t timer_id; 240 ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id)); 241 242 ScopedSignalHandler ssh(SIGALRM, timer_create_NULL_signal_handler); 243 244 ASSERT_EQ(0, timer_create_NULL_signal_handler_invocation_count); 245 246 SetTime(timer_id, 0, 1, 0, 0); 247 usleep(500000); 248 249 ASSERT_EQ(1, timer_create_NULL_signal_handler_invocation_count); 250} 251 252TEST(time, timer_create_EINVAL) { 253 clockid_t invalid_clock = 16; 254 255 // A SIGEV_SIGNAL timer is easy; the kernel does all that. 256 timer_t timer_id; 257 ASSERT_EQ(-1, timer_create(invalid_clock, NULL, &timer_id)); 258 ASSERT_EQ(EINVAL, errno); 259 260 // A SIGEV_THREAD timer is more interesting because we have stuff to clean up. 261 sigevent_t se; 262 memset(&se, 0, sizeof(se)); 263 se.sigev_notify = SIGEV_THREAD; 264 se.sigev_notify_function = NoOpNotifyFunction; 265 ASSERT_EQ(-1, timer_create(invalid_clock, &se, &timer_id)); 266 ASSERT_EQ(EINVAL, errno); 267} 268 269TEST(time, timer_delete_multiple) { 270 timer_t timer_id; 271 ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, NULL, &timer_id)); 272 ASSERT_EQ(0, timer_delete(timer_id)); 273 ASSERT_EQ(-1, timer_delete(timer_id)); 274 ASSERT_EQ(EINVAL, errno); 275 276 sigevent_t se; 277 memset(&se, 0, sizeof(se)); 278 se.sigev_notify = SIGEV_THREAD; 279 se.sigev_notify_function = NoOpNotifyFunction; 280 ASSERT_EQ(0, timer_create(CLOCK_MONOTONIC, &se, &timer_id)); 281 ASSERT_EQ(0, timer_delete(timer_id)); 282 ASSERT_EQ(-1, timer_delete(timer_id)); 283 ASSERT_EQ(EINVAL, errno); 284} 285 286TEST(time, timer_create_multiple) { 287 Counter counter1(Counter::CountNotifyFunction); 288 counter1.Create(); 289 Counter counter2(Counter::CountNotifyFunction); 290 counter2.Create(); 291 Counter counter3(Counter::CountNotifyFunction); 292 counter3.Create(); 293 294 ASSERT_EQ(0, counter1.value); 295 ASSERT_EQ(0, counter2.value); 296 ASSERT_EQ(0, counter3.value); 297 298 SetTime(counter2.timer_id, 0, 1, 0, 0); 299 usleep(500000); 300 301 EXPECT_EQ(0, counter1.value); 302 EXPECT_EQ(1, counter2.value); 303 EXPECT_EQ(0, counter3.value); 304} 305