15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2009 Google Inc. All Rights Reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Nabeel Mian (nabeelmian@google.com) 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Chris Demetriou (cgd@google.com) 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains the unit tests for profile-handler.h interface. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is linked into three separate unit tests: 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// profile-handler_unittest tests basic functionality 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// profile-handler_disable_test tests that the profiler 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is disabled with --install_signal_handlers=false 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// profile-handler_conflict_test tests that the profiler 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is disabled when a SIGPROF handler is registered before InitGoogle. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "profile-handler.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h> 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h> 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/time.h> 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h> 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/simple_mutex.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Some helpful macros for the test class 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TEST_F(cls, fn) void cls :: fn() 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Do we expect the profiler to be enabled? 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_profiler_enabled, true, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "expect profiler to be enabled during tests"); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Should we look at the kernel signal handler settings during the test? 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Not if we're in conflict_test, because we can't distinguish its nop 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// handler from the real one. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_profiler_signal_handler, true, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "check profiler signal handler during tests"); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(csilvers): error-checking on the pthreads routines 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Thread { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Thread() : joinable_(false) { } 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetJoinable(bool value) { joinable_ = value; } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Start() { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_attr_t attr; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_attr_init(&attr); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_attr_setdetachstate(&attr, joinable_ ? PTHREAD_CREATE_JOINABLE 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : PTHREAD_CREATE_DETACHED); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_create(&thread_, &attr, &DoRun, this); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_attr_destroy(&attr); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Join() { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(joinable_); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_join(thread_, NULL); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() = 0; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void* DoRun(void* cls) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerRegisterThread(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<Thread*>(cls)->Run(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_t thread_; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool joinable_; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sleep interval in nano secs. ITIMER_PROF goes off only afer the specified CPU 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// time is consumed. Under heavy load this process may no get scheduled in a 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// timely fashion. Therefore, give enough time (20x of ProfileHandle timer 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// interval 10ms (100Hz)) for this process to accumulate enought CPU time to get 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a profile tick. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int kSleepInterval = 200000000; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sleep interval in nano secs. To ensure that if the timer has expired it is 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reset. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int kTimerResetInterval = 5000000; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Whether each thread has separate timers. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool timer_separate_ = false; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int timer_type_ = ITIMER_PROF; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int signal_number_ = SIGPROF; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Delays processing by the specified number of nano seconds. 'delay_ns' 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// must be less than the number of nano seconds in a second (1000000000). 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Delay(int delay_ns) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kNumNSecInSecond = 1000000000; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_LT(delay_ns, kNumNSecInSecond); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct timespec delay = { 0, delay_ns }; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nanosleep(&delay, 0); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks whether the profile timer is enabled for the current thread. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsTimerEnabled() { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) itimerval current_timer; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, getitimer(timer_type_, ¤t_timer)); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((current_timer.it_value.tv_sec == 0) && 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (current_timer.it_value.tv_usec != 0)) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // May be the timer has expired. Sleep for a bit and check again. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delay(kTimerResetInterval); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, getitimer(timer_type_, ¤t_timer)); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (current_timer.it_value.tv_sec != 0 || 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_timer.it_value.tv_usec != 0); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VirtualTimerGetterThread : public Thread { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VirtualTimerGetterThread() { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&virtual_timer_, 0, sizeof virtual_timer_); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct itimerval virtual_timer_; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Run() { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(0, getitimer(ITIMER_VIRTUAL, &virtual_timer_)); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function checks whether the timers are shared between thread. This 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function spawns a thread, so use it carefully when testing thread-dependent 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// behaviour. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool threads_have_separate_timers() { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct itimerval new_timer_val; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enable the virtual timer in the current thread. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&new_timer_val, 0, sizeof new_timer_val); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_timer_val.it_value.tv_sec = 1000000; // seconds 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(0, setitimer(ITIMER_VIRTUAL, &new_timer_val, NULL)); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Spawn a thread, get the virtual timer's value there. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VirtualTimerGetterThread thread; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread.SetJoinable(true); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread.Start(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread.Join(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Disable timer here. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&new_timer_val, 0, sizeof new_timer_val); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(0, setitimer(ITIMER_VIRTUAL, &new_timer_val, NULL)); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool target_timer_enabled = (thread.virtual_timer_.it_value.tv_sec != 0 || 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread.virtual_timer_.it_value.tv_usec != 0); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!target_timer_enabled) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(INFO, "threads have separate timers"); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(INFO, "threads have shared timers"); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Dummy worker thread to accumulate cpu time. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BusyThread : public Thread { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BusyThread() : stop_work_(false) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Setter/Getters 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool stop_work() { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MutexLock lock(&mu_); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return stop_work_; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_stop_work(bool stop_work) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MutexLock lock(&mu_); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stop_work_ = stop_work; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Protects stop_work_ below. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Mutex mu_; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Whether to stop work? 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool stop_work_; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do work until asked to stop. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Run() { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!stop_work()) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If timers are separate, check that timer is enabled for this thread. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(!timer_separate_ || IsTimerEnabled()); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NullThread : public Thread { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Run() { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If timers are separate, check that timer is enabled for this thread. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(!timer_separate_ || IsTimerEnabled()); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Signal handler which tracks the profile timer ticks. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TickCounter(int sig, siginfo_t* sig_info, void *vuc, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* tick_counter) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* counter = static_cast<int*>(tick_counter); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++(*counter); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class tests the profile-handler.h interface. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProfileHandlerTest { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Determines whether threads have separate timers. 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void SetUpTestCase() { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signal_number_ = (getenv("CPUPROFILE_REALTIME") ? SIGALRM : SIGPROF); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timer_separate_ = threads_have_separate_timers(); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delay(kTimerResetInterval); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets up the profile timers and SIGPROF/SIGALRM handler in a known state. 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It does the following: 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. Unregisters all the callbacks, stops the timer (if shared) and 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // clears out timer_sharing state in the ProfileHandler. This clears 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // out any state left behind by the previous test or during module 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // initialization when the test program was started. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. Spawns two threads which will be registered with the ProfileHandler. 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // At this time ProfileHandler knows if the timers are shared. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3. Starts a busy worker thread to accumulate CPU usage. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset the state of ProfileHandler between each test. This unregisters 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // all callbacks, stops timer (if shared) and clears timer sharing state. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerReset(); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, GetCallbackCount()); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyDisabled(); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ProfileHandler requires at least two threads to be registerd to determine 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whether timers are shared. 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterThread(); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterThread(); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now that two threads are started, verify that the signal handler is 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // disabled and the timers are correctly enabled/disabled. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyDisabled(); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start worker to accumulate cpu usage. 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartWorker(); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerReset(); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stops the worker thread. 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopWorker(); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Starts a no-op thread that gets registered with the ProfileHandler. Waits 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for the thread to stop. 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RegisterThread() { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NullThread t; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t.SetJoinable(true); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t.Start(); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t.Join(); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Starts a busy worker thread to accumulate cpu time. There should be only 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one busy worker running. This is required for the case where there are 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // separate timers for each thread. 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartWorker() { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) busy_worker_ = new BusyThread(); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) busy_worker_->SetJoinable(true); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) busy_worker_->Start(); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for worker to start up and register with the ProfileHandler. 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(nabeelmian) This may not work under very heavy load. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delay(kSleepInterval); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stops the worker thread. 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StopWorker() { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) busy_worker_->set_stop_work(true); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) busy_worker_->Join(); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete busy_worker_; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checks whether SIGPROF/SIGALRM signal handler is enabled. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsSignalEnabled() { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sigaction sa; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(sigaction(signal_number_, NULL, &sa), 0); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((sa.sa_handler == SIG_IGN) || (sa.sa_handler == SIG_DFL)) ? 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false : true; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets the number of callbacks registered with the ProfileHandler. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 GetCallbackCount() { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerState state; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerGetState(&state); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return state.callback_count; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets the current ProfileHandler interrupt count. 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 GetInterruptCount() { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerState state; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerGetState(&state); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return state.interrupts; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verifies that a callback is correctly registered and receiving 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // profile ticks. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void VerifyRegistration(const int& tick_counter) { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check the callback count. 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GT(GetCallbackCount(), 0); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the profile timer is enabled. 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(FLAGS_test_profiler_enabled, IsTimerEnabled()); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the signal handler is enabled. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_test_profiler_signal_handler) { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(FLAGS_test_profiler_enabled, IsSignalEnabled()); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 interrupts_before = GetInterruptCount(); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sleep for a bit and check that tick counter is making progress. 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_tick_count = tick_counter; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delay(kSleepInterval); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_tick_count = tick_counter; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 interrupts_after = GetInterruptCount(); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_test_profiler_enabled) { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GT(new_tick_count, old_tick_count); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GT(interrupts_after, interrupts_before); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(new_tick_count, old_tick_count); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(interrupts_after, interrupts_before); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verifies that a callback is not receiving profile ticks. 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void VerifyUnregistration(const int& tick_counter) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sleep for a bit and check that tick counter is not making progress. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_tick_count = tick_counter; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delay(kSleepInterval); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_tick_count = tick_counter; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(old_tick_count, new_tick_count); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If no callbacks, signal handler and shared timer should be disabled. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetCallbackCount() == 0) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_test_profiler_signal_handler) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(IsSignalEnabled()); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (timer_separate_) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(IsTimerEnabled()); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(IsTimerEnabled()); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verifies that the SIGPROF/SIGALRM interrupt handler is disabled and the 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // timer, if shared, is disabled. Expects the worker to be running. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void VerifyDisabled() { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the signal handler is disabled. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_test_profiler_signal_handler) { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(IsSignalEnabled()); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the callback count is 0. 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, GetCallbackCount()); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the timer is disabled if shared, enabled otherwise. 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (timer_separate_) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(IsTimerEnabled()); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(IsTimerEnabled()); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that the ProfileHandler is not accumulating profile ticks. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 interrupts_before = GetInterruptCount(); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delay(kSleepInterval); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 interrupts_after = GetInterruptCount(); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(interrupts_before, interrupts_after); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Registers a callback and waits for kTimerResetInterval for timers to get 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reset. 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerToken* RegisterCallback(void* callback_arg) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerToken* token = ProfileHandlerRegisterCallback( 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TickCounter, callback_arg); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delay(kTimerResetInterval); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return token; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unregisters a callback and waits for kTimerResetInterval for timers to get 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reset. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UnregisterCallback(ProfileHandlerToken* token) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerUnregisterCallback(token); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delay(kTimerResetInterval); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Busy worker thread to accumulate cpu usage. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BusyThread* busy_worker_; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The tests to run 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RegisterUnregisterCallback(); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void MultipleCallbacks(); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Reset(); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RegisterCallbackBeforeThread(); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RUN(test) do { \ 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Running %s\n", #test); \ 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerTest pht; \ 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pht.SetUp(); \ 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pht.test(); \ 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pht.TearDown(); \ 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int RUN_ALL_TESTS() { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetUpTestCase(); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RUN(RegisterUnregisterCallback); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RUN(MultipleCallbacks); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RUN(Reset); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RUN(RegisterCallbackBeforeThread); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("Done\n"); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies ProfileHandlerRegisterCallback and 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProfileHandlerUnregisterCallback. 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileHandlerTest, RegisterUnregisterCallback) { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tick_count = 0; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerToken* token = RegisterCallback(&tick_count); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyRegistration(tick_count); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnregisterCallback(token); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyUnregistration(tick_count); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies that multiple callbacks can be registered. 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileHandlerTest, MultipleCallbacks) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register first callback. 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int first_tick_count; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerToken* token1 = RegisterCallback(&first_tick_count); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that callback was registered correctly. 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyRegistration(first_tick_count); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, GetCallbackCount()); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register second callback. 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int second_tick_count; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerToken* token2 = RegisterCallback(&second_tick_count); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that callback was registered correctly. 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyRegistration(second_tick_count); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2, GetCallbackCount()); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unregister first callback. 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnregisterCallback(token1); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyUnregistration(first_tick_count); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, GetCallbackCount()); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that second callback is still registered. 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyRegistration(second_tick_count); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unregister second callback. 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnregisterCallback(token2); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyUnregistration(second_tick_count); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, GetCallbackCount()); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that the signal handler and timers are correctly disabled. 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyDisabled(); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies ProfileHandlerReset 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileHandlerTest, Reset) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that the profile timer interrupt is disabled. 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyDisabled(); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int first_tick_count; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterCallback(&first_tick_count); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyRegistration(first_tick_count); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, GetCallbackCount()); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register second callback. 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int second_tick_count; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterCallback(&second_tick_count); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyRegistration(second_tick_count); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2, GetCallbackCount()); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset the profile handler and verify that callback were correctly 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unregistered and timer/signal are disabled. 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerReset(); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyUnregistration(first_tick_count); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyUnregistration(second_tick_count); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyDisabled(); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verifies that ProfileHandler correctly handles a case where a callback was 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// registered before the second thread started. 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileHandlerTest, RegisterCallbackBeforeThread) { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stop the worker. 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopWorker(); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unregister all existing callbacks, stop the timer (if shared), disable 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the signal handler and reset the timer sharing state in the Profile 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handler. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerReset(); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, GetCallbackCount()); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyDisabled(); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start the worker. At this time ProfileHandler doesn't know if timers are 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shared as only one thread has registered so far. 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartWorker(); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register a callback and check that profile ticks are being delivered. 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tick_count; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterCallback(&tick_count); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, GetCallbackCount()); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VerifyRegistration(tick_count); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register a second thread and verify that timer and signal handler are 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // correctly enabled. 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterThread(); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, GetCallbackCount()); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(FLAGS_test_profiler_enabled, IsTimerEnabled()); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_test_profiler_signal_handler) { 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(FLAGS_test_profiler_enabled, IsSignalEnabled()); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char** argv) { 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProfileHandlerTest::RUN_ALL_TESTS(); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 507