Revert of Roll src/third_party/WebKit e0eac24:489c548 (svn 193311:193320) (patchset...
[chromium-blink-merge.git] / third_party / tcmalloc / chromium / src / tests / profile-handler_unittest.cc
blob98cfe6d5bf6826d96045999639c86b39e631251b
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.
14 #include "config.h"
15 #include "profile-handler.h"
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"
24 // Some helpful macros for the test class
25 #define TEST_F(cls, fn) void cls :: fn()
27 // Do we expect the profiler to be enabled?
28 DEFINE_bool(test_profiler_enabled, true,
29 "expect profiler to be enabled during tests");
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");
37 namespace {
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);
52 void Join() {
53 assert(joinable_);
54 pthread_join(thread_, NULL);
56 virtual void Run() = 0;
57 private:
58 static void* DoRun(void* cls) {
59 ProfileHandlerRegisterThread();
60 reinterpret_cast<Thread*>(cls)->Run();
61 return NULL;
63 pthread_t thread_;
64 bool joinable_;
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;
74 // Sleep interval in nano secs. To ensure that if the timer has expired it is
75 // reset.
76 int kTimerResetInterval = 5000000;
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;
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);
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));
102 return (current_timer.it_value.tv_sec != 0 ||
103 current_timer.it_value.tv_usec != 0);
106 class VirtualTimerGetterThread : public Thread {
107 public:
108 VirtualTimerGetterThread() {
109 memset(&virtual_timer_, 0, sizeof virtual_timer_);
111 struct itimerval virtual_timer_;
113 private:
114 void Run() {
115 CHECK_EQ(0, getitimer(ITIMER_VIRTUAL, &virtual_timer_));
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;
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));
130 // Spawn a thread, get the virtual timer's value there.
131 VirtualTimerGetterThread thread;
132 thread.SetJoinable(true);
133 thread.Start();
134 thread.Join();
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));
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;
151 // Dummy worker thread to accumulate cpu time.
152 class BusyThread : public Thread {
153 public:
154 BusyThread() : stop_work_(false) {
157 // Setter/Getters
158 bool stop_work() {
159 MutexLock lock(&mu_);
160 return stop_work_;
162 void set_stop_work(bool stop_work) {
163 MutexLock lock(&mu_);
164 stop_work_ = stop_work;
167 private:
168 // Protects stop_work_ below.
169 Mutex mu_;
170 // Whether to stop work?
171 bool stop_work_;
173 // Do work until asked to stop.
174 void Run() {
175 while (!stop_work()) {
177 // If timers are separate, check that timer is enabled for this thread.
178 EXPECT_TRUE(!timer_separate_ || IsTimerEnabled());
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());
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);
197 // This class tests the profile-handler.h interface.
198 class ProfileHandlerTest {
199 protected:
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);
206 timer_separate_ = threads_have_separate_timers();
207 Delay(kTimerResetInterval);
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();
236 virtual void TearDown() {
237 ProfileHandlerReset();
238 // Stops the worker thread.
239 StopWorker();
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();
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);
263 // Stops the worker thread.
264 void StopWorker() {
265 busy_worker_->set_stop_work(true);
266 busy_worker_->Join();
267 delete busy_worker_;
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;
278 // Gets the number of callbacks registered with the ProfileHandler.
279 uint32 GetCallbackCount() {
280 ProfileHandlerState state;
281 ProfileHandlerGetState(&state);
282 return state.callback_count;
285 // Gets the current ProfileHandler interrupt count.
286 uint64 GetInterruptCount() {
287 ProfileHandlerState state;
288 ProfileHandlerGetState(&state);
289 return state.interrupts;
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());
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);
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());
330 if (timer_separate_) {
331 EXPECT_TRUE(IsTimerEnabled());
332 } else {
333 EXPECT_FALSE(IsTimerEnabled());
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());
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());
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);
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;
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);
376 // Busy worker thread to accumulate cpu usage.
377 BusyThread* busy_worker_;
379 private:
380 // The tests to run
381 void RegisterUnregisterCallback();
382 void MultipleCallbacks();
383 void Reset();
384 void RegisterCallbackBeforeThread();
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)
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;
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);
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());
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());
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);
439 // Unregister second callback.
440 UnregisterCallback(token2);
441 VerifyUnregistration(second_tick_count);
442 EXPECT_EQ(0, GetCallbackCount());
444 // Verify that the signal handler and timers are correctly disabled.
445 VerifyDisabled();
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());
457 // Register second callback.
458 int second_tick_count;
459 RegisterCallback(&second_tick_count);
460 VerifyRegistration(second_tick_count);
461 EXPECT_EQ(2, GetCallbackCount());
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();
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();
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);
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());
502 } // namespace
504 int main(int argc, char** argv) {
505 return ProfileHandlerTest::RUN_ALL_TESTS();