1 // Copyright 2009 Google Inc. All Rights Reserved. 2 // Author: Nabeel Mian (nabeelmian (at) google.com) 3 // Chris Demetriou (cgd (at) google.com) 4 // 5 // This file contains the unit tests for profile-handler.h interface. 6 // 7 // It is linked into three separate unit tests: 8 // profile-handler_unittest tests basic functionality 9 // profile-handler_disable_test tests that the profiler 10 // is disabled with --install_signal_handlers=false 11 // profile-handler_conflict_test tests that the profiler 12 // is disabled when a SIGPROF handler is registered before InitGoogle. 13 14 #include "config.h" 15 #include "profile-handler.h" 16 17 #include <assert.h> 18 #include <pthread.h> 19 #include <sys/time.h> 20 #include <time.h> 21 #include "base/logging.h" 22 #include "base/simple_mutex.h" 23 24 // Some helpful macros for the test class 25 #define TEST_F(cls, fn) void cls :: fn() 26 27 // Do we expect the profiler to be enabled? 28 DEFINE_bool(test_profiler_enabled, true, 29 "expect profiler to be enabled during tests"); 30 31 // Should we look at the kernel signal handler settings during the test? 32 // Not if we're in conflict_test, because we can't distinguish its nop 33 // handler from the real one. 34 DEFINE_bool(test_profiler_signal_handler, true, 35 "check profiler signal handler during tests"); 36 37 namespace { 38 39 // TODO(csilvers): error-checking on the pthreads routines 40 class Thread { 41 public: 42 Thread() : joinable_(false) { } 43 void SetJoinable(bool value) { joinable_ = value; } 44 void Start() { 45 pthread_attr_t attr; 46 pthread_attr_init(&attr); 47 pthread_attr_setdetachstate(&attr, joinable_ ? PTHREAD_CREATE_JOINABLE 48 : PTHREAD_CREATE_DETACHED); 49 pthread_create(&thread_, &attr, &DoRun, this); 50 pthread_attr_destroy(&attr); 51 } 52 void Join() { 53 assert(joinable_); 54 pthread_join(thread_, NULL); 55 } 56 virtual void Run() = 0; 57 private: 58 static void* DoRun(void* cls) { 59 ProfileHandlerRegisterThread(); 60 reinterpret_cast<Thread*>(cls)->Run(); 61 return NULL; 62 } 63 pthread_t thread_; 64 bool joinable_; 65 }; 66 67 // Sleep interval in nano secs. ITIMER_PROF goes off only afer the specified CPU 68 // time is consumed. Under heavy load this process may no get scheduled in a 69 // timely fashion. Therefore, give enough time (20x of ProfileHandle timer 70 // interval 10ms (100Hz)) for this process to accumulate enought CPU time to get 71 // a profile tick. 72 int kSleepInterval = 200000000; 73 74 // Sleep interval in nano secs. To ensure that if the timer has expired it is 75 // reset. 76 int kTimerResetInterval = 5000000; 77 78 // Whether each thread has separate timers. 79 static bool timer_separate_ = false; 80 static int timer_type_ = ITIMER_PROF; 81 static int signal_number_ = SIGPROF; 82 83 // Delays processing by the specified number of nano seconds. 'delay_ns' 84 // must be less than the number of nano seconds in a second (1000000000). 85 void Delay(int delay_ns) { 86 static const int kNumNSecInSecond = 1000000000; 87 EXPECT_LT(delay_ns, kNumNSecInSecond); 88 struct timespec delay = { 0, delay_ns }; 89 nanosleep(&delay, 0); 90 } 91 92 // Checks whether the profile timer is enabled for the current thread. 93 bool IsTimerEnabled() { 94 itimerval current_timer; 95 EXPECT_EQ(0, getitimer(timer_type_, ¤t_timer)); 96 if ((current_timer.it_value.tv_sec == 0) && 97 (current_timer.it_value.tv_usec != 0)) { 98 // May be the timer has expired. Sleep for a bit and check again. 99 Delay(kTimerResetInterval); 100 EXPECT_EQ(0, getitimer(timer_type_, ¤t_timer)); 101 } 102 return (current_timer.it_value.tv_sec != 0 || 103 current_timer.it_value.tv_usec != 0); 104 } 105 106 class VirtualTimerGetterThread : public Thread { 107 public: 108 VirtualTimerGetterThread() { 109 memset(&virtual_timer_, 0, sizeof virtual_timer_); 110 } 111 struct itimerval virtual_timer_; 112 113 private: 114 void Run() { 115 CHECK_EQ(0, getitimer(ITIMER_VIRTUAL, &virtual_timer_)); 116 } 117 }; 118 119 // This function checks whether the timers are shared between thread. This 120 // function spawns a thread, so use it carefully when testing thread-dependent 121 // behaviour. 122 static bool threads_have_separate_timers() { 123 struct itimerval new_timer_val; 124 125 // Enable the virtual timer in the current thread. 126 memset(&new_timer_val, 0, sizeof new_timer_val); 127 new_timer_val.it_value.tv_sec = 1000000; // seconds 128 CHECK_EQ(0, setitimer(ITIMER_VIRTUAL, &new_timer_val, NULL)); 129 130 // Spawn a thread, get the virtual timer's value there. 131 VirtualTimerGetterThread thread; 132 thread.SetJoinable(true); 133 thread.Start(); 134 thread.Join(); 135 136 // Disable timer here. 137 memset(&new_timer_val, 0, sizeof new_timer_val); 138 CHECK_EQ(0, setitimer(ITIMER_VIRTUAL, &new_timer_val, NULL)); 139 140 bool target_timer_enabled = (thread.virtual_timer_.it_value.tv_sec != 0 || 141 thread.virtual_timer_.it_value.tv_usec != 0); 142 if (!target_timer_enabled) { 143 LOG(INFO, "threads have separate timers"); 144 return true; 145 } else { 146 LOG(INFO, "threads have shared timers"); 147 return false; 148 } 149 } 150 151 // Dummy worker thread to accumulate cpu time. 152 class BusyThread : public Thread { 153 public: 154 BusyThread() : stop_work_(false) { 155 } 156 157 // Setter/Getters 158 bool stop_work() { 159 MutexLock lock(&mu_); 160 return stop_work_; 161 } 162 void set_stop_work(bool stop_work) { 163 MutexLock lock(&mu_); 164 stop_work_ = stop_work; 165 } 166 167 private: 168 // Protects stop_work_ below. 169 Mutex mu_; 170 // Whether to stop work? 171 bool stop_work_; 172 173 // Do work until asked to stop. 174 void Run() { 175 while (!stop_work()) { 176 } 177 // If timers are separate, check that timer is enabled for this thread. 178 EXPECT_TRUE(!timer_separate_ || IsTimerEnabled()); 179 } 180 }; 181 182 class NullThread : public Thread { 183 private: 184 void Run() { 185 // If timers are separate, check that timer is enabled for this thread. 186 EXPECT_TRUE(!timer_separate_ || IsTimerEnabled()); 187 } 188 }; 189 190 // Signal handler which tracks the profile timer ticks. 191 static void TickCounter(int sig, siginfo_t* sig_info, void *vuc, 192 void* tick_counter) { 193 int* counter = static_cast<int*>(tick_counter); 194 ++(*counter); 195 } 196 197 // This class tests the profile-handler.h interface. 198 class ProfileHandlerTest { 199 protected: 200 201 // Determines whether threads have separate timers. 202 static void SetUpTestCase() { 203 timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF); 204 signal_number_ = (getenv("CPUPROFILE_REALTIME") ? SIGALRM : SIGPROF); 205 206 timer_separate_ = threads_have_separate_timers(); 207 Delay(kTimerResetInterval); 208 } 209 210 // Sets up the profile timers and SIGPROF/SIGALRM handler in a known state. 211 // It does the following: 212 // 1. Unregisters all the callbacks, stops the timer (if shared) and 213 // clears out timer_sharing state in the ProfileHandler. This clears 214 // out any state left behind by the previous test or during module 215 // initialization when the test program was started. 216 // 2. Spawns two threads which will be registered with the ProfileHandler. 217 // At this time ProfileHandler knows if the timers are shared. 218 // 3. Starts a busy worker thread to accumulate CPU usage. 219 virtual void SetUp() { 220 // Reset the state of ProfileHandler between each test. This unregisters 221 // all callbacks, stops timer (if shared) and clears timer sharing state. 222 ProfileHandlerReset(); 223 EXPECT_EQ(0, GetCallbackCount()); 224 VerifyDisabled(); 225 // ProfileHandler requires at least two threads to be registerd to determine 226 // whether timers are shared. 227 RegisterThread(); 228 RegisterThread(); 229 // Now that two threads are started, verify that the signal handler is 230 // disabled and the timers are correctly enabled/disabled. 231 VerifyDisabled(); 232 // Start worker to accumulate cpu usage. 233 StartWorker(); 234 } 235 236 virtual void TearDown() { 237 ProfileHandlerReset(); 238 // Stops the worker thread. 239 StopWorker(); 240 } 241 242 // Starts a no-op thread that gets registered with the ProfileHandler. Waits 243 // for the thread to stop. 244 void RegisterThread() { 245 NullThread t; 246 t.SetJoinable(true); 247 t.Start(); 248 t.Join(); 249 } 250 251 // Starts a busy worker thread to accumulate cpu time. There should be only 252 // one busy worker running. This is required for the case where there are 253 // separate timers for each thread. 254 void StartWorker() { 255 busy_worker_ = new BusyThread(); 256 busy_worker_->SetJoinable(true); 257 busy_worker_->Start(); 258 // Wait for worker to start up and register with the ProfileHandler. 259 // TODO(nabeelmian) This may not work under very heavy load. 260 Delay(kSleepInterval); 261 } 262 263 // Stops the worker thread. 264 void StopWorker() { 265 busy_worker_->set_stop_work(true); 266 busy_worker_->Join(); 267 delete busy_worker_; 268 } 269 270 // Checks whether SIGPROF/SIGALRM signal handler is enabled. 271 bool IsSignalEnabled() { 272 struct sigaction sa; 273 CHECK_EQ(sigaction(signal_number_, NULL, &sa), 0); 274 return ((sa.sa_handler == SIG_IGN) || (sa.sa_handler == SIG_DFL)) ? 275 false : true; 276 } 277 278 // Gets the number of callbacks registered with the ProfileHandler. 279 uint32 GetCallbackCount() { 280 ProfileHandlerState state; 281 ProfileHandlerGetState(&state); 282 return state.callback_count; 283 } 284 285 // Gets the current ProfileHandler interrupt count. 286 uint64 GetInterruptCount() { 287 ProfileHandlerState state; 288 ProfileHandlerGetState(&state); 289 return state.interrupts; 290 } 291 292 // Verifies that a callback is correctly registered and receiving 293 // profile ticks. 294 void VerifyRegistration(const int& tick_counter) { 295 // Check the callback count. 296 EXPECT_GT(GetCallbackCount(), 0); 297 // Check that the profile timer is enabled. 298 EXPECT_EQ(FLAGS_test_profiler_enabled, IsTimerEnabled()); 299 // Check that the signal handler is enabled. 300 if (FLAGS_test_profiler_signal_handler) { 301 EXPECT_EQ(FLAGS_test_profiler_enabled, IsSignalEnabled()); 302 } 303 uint64 interrupts_before = GetInterruptCount(); 304 // Sleep for a bit and check that tick counter is making progress. 305 int old_tick_count = tick_counter; 306 Delay(kSleepInterval); 307 int new_tick_count = tick_counter; 308 uint64 interrupts_after = GetInterruptCount(); 309 if (FLAGS_test_profiler_enabled) { 310 EXPECT_GT(new_tick_count, old_tick_count); 311 EXPECT_GT(interrupts_after, interrupts_before); 312 } else { 313 EXPECT_EQ(new_tick_count, old_tick_count); 314 EXPECT_EQ(interrupts_after, interrupts_before); 315 } 316 } 317 318 // Verifies that a callback is not receiving profile ticks. 319 void VerifyUnregistration(const int& tick_counter) { 320 // Sleep for a bit and check that tick counter is not making progress. 321 int old_tick_count = tick_counter; 322 Delay(kSleepInterval); 323 int new_tick_count = tick_counter; 324 EXPECT_EQ(old_tick_count, new_tick_count); 325 // If no callbacks, signal handler and shared timer should be disabled. 326 if (GetCallbackCount() == 0) { 327 if (FLAGS_test_profiler_signal_handler) { 328 EXPECT_FALSE(IsSignalEnabled()); 329 } 330 if (timer_separate_) { 331 EXPECT_TRUE(IsTimerEnabled()); 332 } else { 333 EXPECT_FALSE(IsTimerEnabled()); 334 } 335 } 336 } 337 338 // Verifies that the SIGPROF/SIGALRM interrupt handler is disabled and the 339 // timer, if shared, is disabled. Expects the worker to be running. 340 void VerifyDisabled() { 341 // Check that the signal handler is disabled. 342 if (FLAGS_test_profiler_signal_handler) { 343 EXPECT_FALSE(IsSignalEnabled()); 344 } 345 // Check that the callback count is 0. 346 EXPECT_EQ(0, GetCallbackCount()); 347 // Check that the timer is disabled if shared, enabled otherwise. 348 if (timer_separate_) { 349 EXPECT_TRUE(IsTimerEnabled()); 350 } else { 351 EXPECT_FALSE(IsTimerEnabled()); 352 } 353 // Verify that the ProfileHandler is not accumulating profile ticks. 354 uint64 interrupts_before = GetInterruptCount(); 355 Delay(kSleepInterval); 356 uint64 interrupts_after = GetInterruptCount(); 357 EXPECT_EQ(interrupts_before, interrupts_after); 358 } 359 360 // Registers a callback and waits for kTimerResetInterval for timers to get 361 // reset. 362 ProfileHandlerToken* RegisterCallback(void* callback_arg) { 363 ProfileHandlerToken* token = ProfileHandlerRegisterCallback( 364 TickCounter, callback_arg); 365 Delay(kTimerResetInterval); 366 return token; 367 } 368 369 // Unregisters a callback and waits for kTimerResetInterval for timers to get 370 // reset. 371 void UnregisterCallback(ProfileHandlerToken* token) { 372 ProfileHandlerUnregisterCallback(token); 373 Delay(kTimerResetInterval); 374 } 375 376 // Busy worker thread to accumulate cpu usage. 377 BusyThread* busy_worker_; 378 379 private: 380 // The tests to run 381 void RegisterUnregisterCallback(); 382 void MultipleCallbacks(); 383 void Reset(); 384 void RegisterCallbackBeforeThread(); 385 386 public: 387 #define RUN(test) do { \ 388 printf("Running %s\n", #test); \ 389 ProfileHandlerTest pht; \ 390 pht.SetUp(); \ 391 pht.test(); \ 392 pht.TearDown(); \ 393 } while (0) 394 395 static int RUN_ALL_TESTS() { 396 SetUpTestCase(); 397 RUN(RegisterUnregisterCallback); 398 RUN(MultipleCallbacks); 399 RUN(Reset); 400 RUN(RegisterCallbackBeforeThread); 401 printf("Done\n"); 402 return 0; 403 } 404 }; 405 406 // Verifies ProfileHandlerRegisterCallback and 407 // ProfileHandlerUnregisterCallback. 408 TEST_F(ProfileHandlerTest, RegisterUnregisterCallback) { 409 int tick_count = 0; 410 ProfileHandlerToken* token = RegisterCallback(&tick_count); 411 VerifyRegistration(tick_count); 412 UnregisterCallback(token); 413 VerifyUnregistration(tick_count); 414 } 415 416 // Verifies that multiple callbacks can be registered. 417 TEST_F(ProfileHandlerTest, MultipleCallbacks) { 418 // Register first callback. 419 int first_tick_count; 420 ProfileHandlerToken* token1 = RegisterCallback(&first_tick_count); 421 // Check that callback was registered correctly. 422 VerifyRegistration(first_tick_count); 423 EXPECT_EQ(1, GetCallbackCount()); 424 425 // Register second callback. 426 int second_tick_count; 427 ProfileHandlerToken* token2 = RegisterCallback(&second_tick_count); 428 // Check that callback was registered correctly. 429 VerifyRegistration(second_tick_count); 430 EXPECT_EQ(2, GetCallbackCount()); 431 432 // Unregister first callback. 433 UnregisterCallback(token1); 434 VerifyUnregistration(first_tick_count); 435 EXPECT_EQ(1, GetCallbackCount()); 436 // Verify that second callback is still registered. 437 VerifyRegistration(second_tick_count); 438 439 // Unregister second callback. 440 UnregisterCallback(token2); 441 VerifyUnregistration(second_tick_count); 442 EXPECT_EQ(0, GetCallbackCount()); 443 444 // Verify that the signal handler and timers are correctly disabled. 445 VerifyDisabled(); 446 } 447 448 // Verifies ProfileHandlerReset 449 TEST_F(ProfileHandlerTest, Reset) { 450 // Verify that the profile timer interrupt is disabled. 451 VerifyDisabled(); 452 int first_tick_count; 453 RegisterCallback(&first_tick_count); 454 VerifyRegistration(first_tick_count); 455 EXPECT_EQ(1, GetCallbackCount()); 456 457 // Register second callback. 458 int second_tick_count; 459 RegisterCallback(&second_tick_count); 460 VerifyRegistration(second_tick_count); 461 EXPECT_EQ(2, GetCallbackCount()); 462 463 // Reset the profile handler and verify that callback were correctly 464 // unregistered and timer/signal are disabled. 465 ProfileHandlerReset(); 466 VerifyUnregistration(first_tick_count); 467 VerifyUnregistration(second_tick_count); 468 VerifyDisabled(); 469 } 470 471 // Verifies that ProfileHandler correctly handles a case where a callback was 472 // registered before the second thread started. 473 TEST_F(ProfileHandlerTest, RegisterCallbackBeforeThread) { 474 // Stop the worker. 475 StopWorker(); 476 // Unregister all existing callbacks, stop the timer (if shared), disable 477 // the signal handler and reset the timer sharing state in the Profile 478 // Handler. 479 ProfileHandlerReset(); 480 EXPECT_EQ(0, GetCallbackCount()); 481 VerifyDisabled(); 482 483 // Start the worker. At this time ProfileHandler doesn't know if timers are 484 // shared as only one thread has registered so far. 485 StartWorker(); 486 // Register a callback and check that profile ticks are being delivered. 487 int tick_count; 488 RegisterCallback(&tick_count); 489 EXPECT_EQ(1, GetCallbackCount()); 490 VerifyRegistration(tick_count); 491 492 // Register a second thread and verify that timer and signal handler are 493 // correctly enabled. 494 RegisterThread(); 495 EXPECT_EQ(1, GetCallbackCount()); 496 EXPECT_EQ(FLAGS_test_profiler_enabled, IsTimerEnabled()); 497 if (FLAGS_test_profiler_signal_handler) { 498 EXPECT_EQ(FLAGS_test_profiler_enabled, IsSignalEnabled()); 499 } 500 } 501 502 } // namespace 503 504 int main(int argc, char** argv) { 505 return ProfileHandlerTest::RUN_ALL_TESTS(); 506 } 507