Home | History | Annotate | Download | only in tests
      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_, &current_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_, &current_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