1// Copyright 2009 Google Inc. All Rights Reserved.
2// Author: Nabeel Mian (nabeelmian@google.com)
3//         Chris Demetriou (cgd@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?
28DEFINE_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.
34DEFINE_bool(test_profiler_signal_handler, true,
35            "check profiler signal handler during tests");
36
37namespace {
38
39// TODO(csilvers): error-checking on the pthreads routines
40class 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.
72int kSleepInterval = 200000000;
73
74// Sleep interval in nano secs. To ensure that if the timer has expired it is
75// reset.
76int kTimerResetInterval = 5000000;
77
78// Whether each thread has separate timers.
79static bool timer_separate_ = false;
80static int timer_type_ = ITIMER_PROF;
81static 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).
85void 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.
93bool 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
106class 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.
122static 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.
152class 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
182class 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.
191static 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.
198class 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.
408TEST_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.
417TEST_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
449TEST_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.
473TEST_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
504int main(int argc, char** argv) {
505  return ProfileHandlerTest::RUN_ALL_TESTS();
506}
507