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