1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "base/basictypes.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_split.h"
16 #include "base/strings/string_tokenizer.h"
17 #include "base/synchronization/condition_variable.h"
18 #include "base/synchronization/lock.h"
19 #include "base/threading/platform_thread.h"
20 #include "base/time/time.h"
21 #include "build/build_config.h"
22 #include "chrome/browser/metrics/thread_watcher.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "content/public/test/test_browser_thread.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "testing/platform_test.h"
28 using base::TimeDelta
;
29 using base::TimeTicks
;
30 using content::BrowserThread
;
33 INITIALIZED
, // Created ThreadWatch object.
34 ACTIVATED
, // Thread watching activated.
35 SENT_PING
, // Sent ping message to watched thread.
36 RECEIVED_PONG
, // Received Pong message.
37 DEACTIVATED
, // Thread watching de-activated.
42 STARTED_WAITING
, // Start waiting for state_ to change to expected_state.
43 STOPPED_WAITING
, // Done with the waiting.
44 ALL_DONE
, // Done with waiting for STOPPED_WAITING.
47 enum CheckResponseState
{
49 SUCCESSFUL
, // CheckResponse was successful.
50 FAILED
, // CheckResponse has failed.
53 // This class helps to track and manipulate thread state during tests. This
54 // class also has utility method to simulate hanging of watched thread by making
55 // the watched thread wait for a very long time by posting a task on watched
56 // thread that keeps it busy. It also has an utility method to block running of
57 // tests until ThreadWatcher object's post-condition state changes to an
59 class CustomThreadWatcher
: public ThreadWatcher
{
61 base::Lock custom_lock_
;
62 base::ConditionVariable state_changed_
;
63 State thread_watcher_state_
;
64 WaitState wait_state_
;
65 CheckResponseState check_response_state_
;
67 uint64 pong_received_
;
68 base::subtle::Atomic32 success_response_
;
69 base::subtle::Atomic32 failed_response_
;
70 base::TimeTicks saved_ping_time_
;
71 uint64 saved_ping_sequence_number_
;
73 CustomThreadWatcher(const BrowserThread::ID thread_id
,
74 const std::string thread_name
,
75 const TimeDelta
& sleep_time
,
76 const TimeDelta
& unresponsive_time
)
77 : ThreadWatcher(WatchingParams(thread_id
, thread_name
, sleep_time
,
78 unresponsive_time
, ThreadWatcherList::kUnresponsiveCount
,
79 true, ThreadWatcherList::kLiveThreadsThreshold
)),
80 state_changed_(&custom_lock_
),
81 thread_watcher_state_(INITIALIZED
),
82 wait_state_(UNINITIALIZED
),
83 check_response_state_(UNKNOWN
),
88 saved_ping_time_(base::TimeTicks::Now()),
89 saved_ping_sequence_number_(0) {
92 State
UpdateState(State new_state
) {
95 base::AutoLock
auto_lock(custom_lock_
);
96 old_state
= thread_watcher_state_
;
97 if (old_state
!= DEACTIVATED
)
98 thread_watcher_state_
= new_state
;
99 if (new_state
== SENT_PING
)
101 if (new_state
== RECEIVED_PONG
)
103 saved_ping_time_
= ping_time();
104 saved_ping_sequence_number_
= ping_sequence_number();
106 state_changed_
.Broadcast();
110 WaitState
UpdateWaitState(WaitState new_state
) {
113 base::AutoLock
auto_lock(custom_lock_
);
114 old_state
= wait_state_
;
115 wait_state_
= new_state
;
117 state_changed_
.Broadcast();
121 void ActivateThreadWatching() override
{
122 State old_state
= UpdateState(ACTIVATED
);
123 EXPECT_EQ(old_state
, INITIALIZED
);
124 ThreadWatcher::ActivateThreadWatching();
127 void DeActivateThreadWatching() override
{
128 State old_state
= UpdateState(DEACTIVATED
);
129 EXPECT_TRUE(old_state
== ACTIVATED
|| old_state
== SENT_PING
||
130 old_state
== RECEIVED_PONG
);
131 ThreadWatcher::DeActivateThreadWatching();
134 void PostPingMessage() override
{
135 State old_state
= UpdateState(SENT_PING
);
136 EXPECT_TRUE(old_state
== ACTIVATED
|| old_state
== RECEIVED_PONG
);
137 ThreadWatcher::PostPingMessage();
140 void OnPongMessage(uint64 ping_sequence_number
) override
{
141 State old_state
= UpdateState(RECEIVED_PONG
);
142 EXPECT_TRUE(old_state
== SENT_PING
|| old_state
== DEACTIVATED
);
143 ThreadWatcher::OnPongMessage(ping_sequence_number
);
146 void OnCheckResponsiveness(uint64 ping_sequence_number
) override
{
147 ThreadWatcher::OnCheckResponsiveness(ping_sequence_number
);
149 base::AutoLock
auto_lock(custom_lock_
);
151 base::subtle::Release_Store(&success_response_
,
152 base::subtle::Acquire_Load(&success_response_
) + 1);
153 check_response_state_
= SUCCESSFUL
;
155 base::subtle::Release_Store(&failed_response_
,
156 base::subtle::Acquire_Load(&failed_response_
) + 1);
157 check_response_state_
= FAILED
;
160 // Broadcast to indicate we have checked responsiveness of the thread that
162 state_changed_
.Broadcast();
165 void WaitForWaitStateChange(TimeDelta wait_time
, WaitState expected_state
) {
166 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
167 TimeTicks end_time
= TimeTicks::Now() + wait_time
;
169 base::AutoLock
auto_lock(custom_lock_
);
170 while (wait_state_
!= expected_state
&& TimeTicks::Now() < end_time
)
171 state_changed_
.TimedWait(end_time
- TimeTicks::Now());
175 void VeryLongMethod(TimeDelta wait_time
) {
176 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
177 WaitForWaitStateChange(wait_time
, STOPPED_WAITING
);
178 UpdateWaitState(ALL_DONE
);
181 State
WaitForStateChange(const TimeDelta
& wait_time
, State expected_state
) {
182 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
183 UpdateWaitState(STARTED_WAITING
);
185 State exit_state
= INITIALIZED
;
186 // Keep the thread that is running the tests waiting until ThreadWatcher
187 // object's state changes to the expected_state or until wait_time elapses.
188 for (uint32 i
= 0; i
< unresponsive_threshold_
; ++i
) {
189 TimeTicks end_time
= TimeTicks::Now() + wait_time
;
191 base::AutoLock
auto_lock(custom_lock_
);
192 while (thread_watcher_state_
!= expected_state
&&
193 TimeTicks::Now() < end_time
) {
194 TimeDelta state_change_wait_time
= end_time
- TimeTicks::Now();
195 state_changed_
.TimedWait(state_change_wait_time
);
197 // Capture the thread_watcher_state_ before it changes and return it
199 exit_state
= thread_watcher_state_
;
200 if (exit_state
== expected_state
)
204 UpdateWaitState(STOPPED_WAITING
);
208 CheckResponseState
WaitForCheckResponse(const TimeDelta
& wait_time
,
209 CheckResponseState expected_state
) {
210 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
211 UpdateWaitState(STARTED_WAITING
);
213 CheckResponseState exit_state
= UNKNOWN
;
214 // Keep the thread that is running the tests waiting until ThreadWatcher
215 // object's check_response_state_ changes to the expected_state or until
216 // wait_time elapses.
217 for (uint32 i
= 0; i
< unresponsive_threshold_
; ++i
) {
218 TimeTicks end_time
= TimeTicks::Now() + wait_time
;
220 base::AutoLock
auto_lock(custom_lock_
);
221 while (check_response_state_
!= expected_state
&&
222 TimeTicks::Now() < end_time
) {
223 TimeDelta state_change_wait_time
= end_time
- TimeTicks::Now();
224 state_changed_
.TimedWait(state_change_wait_time
);
226 // Capture the check_response_state_ before it changes and return it
228 exit_state
= check_response_state_
;
229 if (exit_state
== expected_state
)
233 UpdateWaitState(STOPPED_WAITING
);
238 class ThreadWatcherTest
: public ::testing::Test
{
240 static const TimeDelta kSleepTime
;
241 static const TimeDelta kUnresponsiveTime
;
242 static const BrowserThread::ID io_thread_id
;
243 static const std::string io_thread_name
;
244 static const BrowserThread::ID db_thread_id
;
245 static const std::string db_thread_name
;
246 static const std::string crash_on_hang_seconds
;
247 static const std::string crash_on_hang_thread_names
;
248 static const std::string thread_names_and_live_threshold
;
249 static const std::string crash_on_hang_thread_data
;
250 CustomThreadWatcher
* io_watcher_
;
251 CustomThreadWatcher
* db_watcher_
;
252 ThreadWatcherList
* thread_watcher_list_
;
255 : setup_complete_(&lock_
),
256 initialized_(false) {
257 db_thread_
.reset(new content::TestBrowserThread(BrowserThread::DB
));
258 io_thread_
.reset(new content::TestBrowserThread(BrowserThread::IO
));
259 watchdog_thread_
.reset(new WatchDogThread());
262 watchdog_thread_
->Start();
264 WatchDogThread::PostTask(
266 base::Bind(&ThreadWatcherTest::SetUpObjects
, base::Unretained(this)));
268 WaitForSetUp(TimeDelta::FromMinutes(1));
271 void SetUpObjects() {
272 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
274 // Setup the registry for thread watchers.
275 thread_watcher_list_
= new ThreadWatcherList();
277 // Create thread watcher object for the IO thread.
278 io_watcher_
= new CustomThreadWatcher(io_thread_id
, io_thread_name
,
279 kSleepTime
, kUnresponsiveTime
);
280 EXPECT_EQ(io_watcher_
, thread_watcher_list_
->Find(io_thread_id
));
282 // Create thread watcher object for the DB thread.
283 db_watcher_
= new CustomThreadWatcher(
284 db_thread_id
, db_thread_name
, kSleepTime
, kUnresponsiveTime
);
285 EXPECT_EQ(db_watcher_
, thread_watcher_list_
->Find(db_thread_id
));
288 base::AutoLock
lock(lock_
);
291 setup_complete_
.Signal();
294 void WaitForSetUp(TimeDelta wait_time
) {
295 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
296 TimeTicks end_time
= TimeTicks::Now() + wait_time
;
298 base::AutoLock
auto_lock(lock_
);
299 while (!initialized_
&& TimeTicks::Now() < end_time
)
300 setup_complete_
.TimedWait(end_time
- TimeTicks::Now());
304 ~ThreadWatcherTest() override
{
305 ThreadWatcherList::DeleteAll();
310 watchdog_thread_
.reset();
311 thread_watcher_list_
= NULL
;
316 base::ConditionVariable setup_complete_
;
318 scoped_ptr
<content::TestBrowserThread
> db_thread_
;
319 scoped_ptr
<content::TestBrowserThread
> io_thread_
;
320 scoped_ptr
<WatchDogThread
> watchdog_thread_
;
323 // Define static constants.
324 const TimeDelta
ThreadWatcherTest::kSleepTime
=
325 TimeDelta::FromMilliseconds(50);
326 const TimeDelta
ThreadWatcherTest::kUnresponsiveTime
=
327 TimeDelta::FromMilliseconds(500);
328 const BrowserThread::ID
ThreadWatcherTest::io_thread_id
= BrowserThread::IO
;
329 const std::string
ThreadWatcherTest::io_thread_name
= "IO";
330 const BrowserThread::ID
ThreadWatcherTest::db_thread_id
= BrowserThread::DB
;
331 const std::string
ThreadWatcherTest::db_thread_name
= "DB";
332 const std::string
ThreadWatcherTest::crash_on_hang_thread_names
= "UI,IO";
333 const std::string
ThreadWatcherTest::thread_names_and_live_threshold
=
335 const std::string
ThreadWatcherTest::crash_on_hang_thread_data
=
336 "UI:5:12,IO:5:12,FILE:5:12";
338 TEST_F(ThreadWatcherTest
, ThreadNamesOnlyArgs
) {
339 // Setup command_line arguments.
340 base::CommandLine
command_line(base::CommandLine::NO_PROGRAM
);
341 command_line
.AppendSwitchASCII(switches::kCrashOnHangThreads
,
342 crash_on_hang_thread_names
);
344 // Parse command_line arguments.
345 ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads
;
346 uint32 unresponsive_threshold
;
347 ThreadWatcherList::ParseCommandLine(command_line
,
348 &unresponsive_threshold
,
349 &crash_on_hang_threads
);
352 base::StringTokenizer
tokens(crash_on_hang_thread_names
, ",");
353 std::vector
<std::string
> values
;
354 while (tokens
.GetNext()) {
355 const std::string
& token
= tokens
.token();
356 base::SplitString(token
, ':', &values
);
357 std::string thread_name
= values
[0];
359 ThreadWatcherList::CrashOnHangThreadMap::iterator it
=
360 crash_on_hang_threads
.find(thread_name
);
361 bool crash_on_hang
= (it
!= crash_on_hang_threads
.end());
362 EXPECT_TRUE(crash_on_hang
);
363 EXPECT_LT(0u, it
->second
.live_threads_threshold
);
364 EXPECT_LT(0u, it
->second
.unresponsive_threshold
);
368 TEST_F(ThreadWatcherTest
, ThreadNamesAndLiveThresholdArgs
) {
369 // Setup command_line arguments.
370 base::CommandLine
command_line(base::CommandLine::NO_PROGRAM
);
371 command_line
.AppendSwitchASCII(switches::kCrashOnHangThreads
,
372 thread_names_and_live_threshold
);
374 // Parse command_line arguments.
375 ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads
;
376 uint32 unresponsive_threshold
;
377 ThreadWatcherList::ParseCommandLine(command_line
,
378 &unresponsive_threshold
,
379 &crash_on_hang_threads
);
382 base::StringTokenizer
tokens(thread_names_and_live_threshold
, ",");
383 std::vector
<std::string
> values
;
384 while (tokens
.GetNext()) {
385 const std::string
& token
= tokens
.token();
386 base::SplitString(token
, ':', &values
);
387 std::string thread_name
= values
[0];
389 ThreadWatcherList::CrashOnHangThreadMap::iterator it
=
390 crash_on_hang_threads
.find(thread_name
);
391 bool crash_on_hang
= (it
!= crash_on_hang_threads
.end());
392 EXPECT_TRUE(crash_on_hang
);
393 EXPECT_EQ(4u, it
->second
.live_threads_threshold
);
394 EXPECT_LT(0u, it
->second
.unresponsive_threshold
);
398 TEST_F(ThreadWatcherTest
, CrashOnHangThreadsAllArgs
) {
399 // Setup command_line arguments.
400 base::CommandLine
command_line(base::CommandLine::NO_PROGRAM
);
401 command_line
.AppendSwitchASCII(switches::kCrashOnHangThreads
,
402 crash_on_hang_thread_data
);
404 // Parse command_line arguments.
405 ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads
;
406 uint32 unresponsive_threshold
;
407 ThreadWatcherList::ParseCommandLine(command_line
,
408 &unresponsive_threshold
,
409 &crash_on_hang_threads
);
412 base::StringTokenizer
tokens(crash_on_hang_thread_data
, ",");
413 std::vector
<std::string
> values
;
414 while (tokens
.GetNext()) {
415 const std::string
& token
= tokens
.token();
416 base::SplitString(token
, ':', &values
);
417 std::string thread_name
= values
[0];
419 ThreadWatcherList::CrashOnHangThreadMap::iterator it
=
420 crash_on_hang_threads
.find(thread_name
);
422 bool crash_on_hang
= (it
!= crash_on_hang_threads
.end());
423 EXPECT_TRUE(crash_on_hang
);
425 uint32 crash_live_threads_threshold
= it
->second
.live_threads_threshold
;
426 EXPECT_EQ(5u, crash_live_threads_threshold
);
428 uint32 crash_unresponsive_threshold
= it
->second
.unresponsive_threshold
;
429 uint32 crash_on_unresponsive_seconds
=
430 ThreadWatcherList::kUnresponsiveSeconds
* crash_unresponsive_threshold
;
431 EXPECT_EQ(12u, crash_on_unresponsive_seconds
);
435 // Test registration. When thread_watcher_list_ goes out of scope after
436 // TearDown, all thread watcher objects will be deleted.
437 TEST_F(ThreadWatcherTest
, Registration
) {
438 // Check ThreadWatcher object has all correct parameters.
439 EXPECT_EQ(io_thread_id
, io_watcher_
->thread_id());
440 EXPECT_EQ(io_thread_name
, io_watcher_
->thread_name());
441 EXPECT_EQ(kSleepTime
, io_watcher_
->sleep_time());
442 EXPECT_EQ(kUnresponsiveTime
, io_watcher_
->unresponsive_time());
443 EXPECT_FALSE(io_watcher_
->active());
445 // Check ThreadWatcher object of watched DB thread has correct data.
446 EXPECT_EQ(db_thread_id
, db_watcher_
->thread_id());
447 EXPECT_EQ(db_thread_name
, db_watcher_
->thread_name());
448 EXPECT_EQ(kSleepTime
, db_watcher_
->sleep_time());
449 EXPECT_EQ(kUnresponsiveTime
, db_watcher_
->unresponsive_time());
450 EXPECT_FALSE(db_watcher_
->active());
453 // Test ActivateThreadWatching and DeActivateThreadWatching of IO thread. This
454 // method also checks that pong message was sent by the watched thread and pong
455 // message was received by the WatchDogThread. It also checks that
456 // OnCheckResponsiveness has verified the ping-pong mechanism and the watched
457 // thread is not hung.
458 TEST_F(ThreadWatcherTest
, ThreadResponding
) {
459 TimeTicks time_before_ping
= TimeTicks::Now();
460 // Activate watching IO thread.
461 WatchDogThread::PostTask(
463 base::Bind(&ThreadWatcher::ActivateThreadWatching
,
464 base::Unretained(io_watcher_
)));
466 // Activate would have started ping/pong messaging. Expect atleast one
467 // ping/pong messaging sequence to happen.
468 io_watcher_
->WaitForStateChange(kSleepTime
+ TimeDelta::FromMinutes(1),
470 EXPECT_GT(io_watcher_
->ping_sent_
, static_cast<uint64
>(0));
471 EXPECT_GT(io_watcher_
->pong_received_
, static_cast<uint64
>(0));
472 EXPECT_TRUE(io_watcher_
->active());
473 EXPECT_GE(io_watcher_
->saved_ping_time_
, time_before_ping
);
474 EXPECT_GE(io_watcher_
->saved_ping_sequence_number_
, static_cast<uint64
>(0));
476 // Verify watched thread is responding with ping/pong messaging.
477 io_watcher_
->WaitForCheckResponse(
478 kUnresponsiveTime
+ TimeDelta::FromMinutes(1), SUCCESSFUL
);
479 EXPECT_GT(base::subtle::NoBarrier_Load(&(io_watcher_
->success_response_
)),
480 static_cast<base::subtle::Atomic32
>(0));
481 EXPECT_EQ(base::subtle::NoBarrier_Load(&(io_watcher_
->failed_response_
)),
482 static_cast<base::subtle::Atomic32
>(0));
484 // DeActivate thread watching for shutdown.
485 WatchDogThread::PostTask(
487 base::Bind(&ThreadWatcher::DeActivateThreadWatching
,
488 base::Unretained(io_watcher_
)));
491 // This test posts a task on watched thread that takes very long time (this is
492 // to simulate hanging of watched thread). It then checks for
493 // OnCheckResponsiveness raising an alert (OnCheckResponsiveness returns false
494 // if the watched thread is not responding).
495 TEST_F(ThreadWatcherTest
, ThreadNotResponding
) {
496 // Simulate hanging of watched thread by making the watched thread wait for a
497 // very long time by posting a task on watched thread that keeps it busy.
498 // It is safe to use base::Unretained because test is waiting for the method
500 BrowserThread::PostTask(
503 base::Bind(&CustomThreadWatcher::VeryLongMethod
,
504 base::Unretained(io_watcher_
),
505 kUnresponsiveTime
* 10));
507 // Activate thread watching.
508 WatchDogThread::PostTask(
510 base::Bind(&ThreadWatcher::ActivateThreadWatching
,
511 base::Unretained(io_watcher_
)));
513 // Verify watched thread is not responding for ping messages.
514 io_watcher_
->WaitForCheckResponse(
515 kUnresponsiveTime
+ TimeDelta::FromMinutes(1), FAILED
);
516 EXPECT_EQ(base::subtle::NoBarrier_Load(&(io_watcher_
->success_response_
)),
517 static_cast<base::subtle::Atomic32
>(0));
518 EXPECT_GT(base::subtle::NoBarrier_Load(&(io_watcher_
->failed_response_
)),
519 static_cast<base::subtle::Atomic32
>(0));
521 // DeActivate thread watching for shutdown.
522 WatchDogThread::PostTask(
524 base::Bind(&ThreadWatcher::DeActivateThreadWatching
,
525 base::Unretained(io_watcher_
)));
527 // Wait for the io_watcher_'s VeryLongMethod to finish.
528 io_watcher_
->WaitForWaitStateChange(kUnresponsiveTime
* 10, ALL_DONE
);
531 // Test watching of multiple threads with all threads not responding.
532 TEST_F(ThreadWatcherTest
, MultipleThreadsResponding
) {
533 // Check for DB thread to perform ping/pong messaging.
534 WatchDogThread::PostTask(
536 base::Bind(&ThreadWatcher::ActivateThreadWatching
,
537 base::Unretained(db_watcher_
)));
539 // Check for IO thread to perform ping/pong messaging.
540 WatchDogThread::PostTask(
542 base::Bind(&ThreadWatcher::ActivateThreadWatching
,
543 base::Unretained(io_watcher_
)));
545 // Verify DB thread is responding with ping/pong messaging.
546 db_watcher_
->WaitForCheckResponse(
547 kUnresponsiveTime
+ TimeDelta::FromMinutes(1), SUCCESSFUL
);
548 EXPECT_GT(db_watcher_
->ping_sent_
, static_cast<uint64
>(0));
549 EXPECT_GT(db_watcher_
->pong_received_
, static_cast<uint64
>(0));
550 EXPECT_GE(db_watcher_
->ping_sequence_number_
, static_cast<uint64
>(0));
551 EXPECT_GT(base::subtle::NoBarrier_Load(&(db_watcher_
->success_response_
)),
552 static_cast<base::subtle::Atomic32
>(0));
553 EXPECT_EQ(base::subtle::NoBarrier_Load(&(db_watcher_
->failed_response_
)),
554 static_cast<base::subtle::Atomic32
>(0));
556 // Verify IO thread is responding with ping/pong messaging.
557 io_watcher_
->WaitForCheckResponse(
558 kUnresponsiveTime
+ TimeDelta::FromMinutes(1), SUCCESSFUL
);
559 EXPECT_GT(io_watcher_
->ping_sent_
, static_cast<uint64
>(0));
560 EXPECT_GT(io_watcher_
->pong_received_
, static_cast<uint64
>(0));
561 EXPECT_GE(io_watcher_
->ping_sequence_number_
, static_cast<uint64
>(0));
562 EXPECT_GT(base::subtle::NoBarrier_Load(&(io_watcher_
->success_response_
)),
563 static_cast<base::subtle::Atomic32
>(0));
564 EXPECT_EQ(base::subtle::NoBarrier_Load(&(io_watcher_
->failed_response_
)),
565 static_cast<base::subtle::Atomic32
>(0));
567 // DeActivate thread watching for shutdown.
568 WatchDogThread::PostTask(
570 base::Bind(&ThreadWatcher::DeActivateThreadWatching
,
571 base::Unretained(io_watcher_
)));
573 WatchDogThread::PostTask(
575 base::Bind(&ThreadWatcher::DeActivateThreadWatching
,
576 base::Unretained(db_watcher_
)));
579 // Test watching of multiple threads with one of the threads not responding.
580 TEST_F(ThreadWatcherTest
, MultipleThreadsNotResponding
) {
581 // Simulate hanging of watched thread by making the watched thread wait for a
582 // very long time by posting a task on watched thread that keeps it busy.
583 // It is safe ot use base::Unretained because test is waiting for the method
585 BrowserThread::PostTask(
588 base::Bind(&CustomThreadWatcher::VeryLongMethod
,
589 base::Unretained(io_watcher_
),
590 kUnresponsiveTime
* 10));
592 // Activate watching of DB thread.
593 WatchDogThread::PostTask(
595 base::Bind(&ThreadWatcher::ActivateThreadWatching
,
596 base::Unretained(db_watcher_
)));
598 // Activate watching of IO thread.
599 WatchDogThread::PostTask(
601 base::Bind(&ThreadWatcher::ActivateThreadWatching
,
602 base::Unretained(io_watcher_
)));
604 // Verify DB thread is responding with ping/pong messaging.
605 db_watcher_
->WaitForCheckResponse(
606 kUnresponsiveTime
+ TimeDelta::FromMinutes(1), SUCCESSFUL
);
607 EXPECT_GT(base::subtle::NoBarrier_Load(&(db_watcher_
->success_response_
)),
608 static_cast<base::subtle::Atomic32
>(0));
609 EXPECT_EQ(base::subtle::NoBarrier_Load(&(db_watcher_
->failed_response_
)),
610 static_cast<base::subtle::Atomic32
>(0));
612 // Verify IO thread is not responding for ping messages.
613 io_watcher_
->WaitForCheckResponse(
614 kUnresponsiveTime
+ TimeDelta::FromMinutes(1), FAILED
);
615 EXPECT_EQ(base::subtle::NoBarrier_Load(&(io_watcher_
->success_response_
)),
616 static_cast<base::subtle::Atomic32
>(0));
617 EXPECT_GT(base::subtle::NoBarrier_Load(&(io_watcher_
->failed_response_
)),
618 static_cast<base::subtle::Atomic32
>(0));
620 // DeActivate thread watching for shutdown.
621 WatchDogThread::PostTask(
623 base::Bind(&ThreadWatcher::DeActivateThreadWatching
,
624 base::Unretained(io_watcher_
)));
625 WatchDogThread::PostTask(
627 base::Bind(&ThreadWatcher::DeActivateThreadWatching
,
628 base::Unretained(db_watcher_
)));
630 // Wait for the io_watcher_'s VeryLongMethod to finish.
631 io_watcher_
->WaitForWaitStateChange(kUnresponsiveTime
* 10, ALL_DONE
);
634 class ThreadWatcherListTest
: public ::testing::Test
{
636 ThreadWatcherListTest()
638 state_available_(false),
639 has_thread_watcher_list_(false),
643 void ReadStateOnWatchDogThread() {
644 CHECK(WatchDogThread::CurrentlyOnWatchDogThread());
646 base::AutoLock
auto_lock(lock_
);
647 has_thread_watcher_list_
=
648 ThreadWatcherList::g_thread_watcher_list_
!= NULL
;
649 stopped_
= ThreadWatcherList::g_stopped_
;
650 state_available_
= true;
655 void CheckState(bool has_thread_watcher_list
,
657 const char* const msg
) {
658 CHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
660 base::AutoLock
auto_lock(lock_
);
661 state_available_
= false;
664 WatchDogThread::PostTask(
666 base::Bind(&ThreadWatcherListTest::ReadStateOnWatchDogThread
,
667 base::Unretained(this)));
669 base::AutoLock
auto_lock(lock_
);
670 while (!state_available_
)
673 EXPECT_EQ(has_thread_watcher_list
, has_thread_watcher_list_
) << msg
;
674 EXPECT_EQ(stopped
, stopped_
) << msg
;
679 base::ConditionVariable done_
;
681 bool state_available_
;
682 bool has_thread_watcher_list_
;
686 TEST_F(ThreadWatcherListTest
, Restart
) {
687 ThreadWatcherList::g_initialize_delay_seconds
= 1;
689 base::MessageLoopForUI message_loop_for_ui
;
690 content::TestBrowserThread
ui_thread(BrowserThread::UI
, &message_loop_for_ui
);
692 scoped_ptr
<WatchDogThread
> watchdog_thread_(new WatchDogThread());
693 watchdog_thread_
->Start();
695 // See http://crbug.com/347887.
696 // StartWatchingAll() will PostDelayedTask to create g_thread_watcher_list_,
697 // whilst StopWatchingAll() will just PostTask to destroy it.
698 // Ensure that when Stop is called, Start will NOT create
699 // g_thread_watcher_list_ later on.
700 ThreadWatcherList::StartWatchingAll(*base::CommandLine::ForCurrentProcess());
701 ThreadWatcherList::StopWatchingAll();
702 message_loop_for_ui
.PostDelayedTask(
704 message_loop_for_ui
.QuitClosure(),
705 base::TimeDelta::FromSeconds(
706 ThreadWatcherList::g_initialize_delay_seconds
));
707 message_loop_for_ui
.Run();
709 CheckState(false /* has_thread_watcher_list */,
713 // Proceed with just |StartWatchingAll| and ensure it'll be started.
714 ThreadWatcherList::StartWatchingAll(*base::CommandLine::ForCurrentProcess());
715 message_loop_for_ui
.PostDelayedTask(
717 message_loop_for_ui
.QuitClosure(),
718 base::TimeDelta::FromSeconds(
719 ThreadWatcherList::g_initialize_delay_seconds
+ 1));
720 message_loop_for_ui
.Run();
722 CheckState(true /* has_thread_watcher_list */,
726 // Finally, StopWatchingAll() must stop.
727 ThreadWatcherList::StopWatchingAll();
728 message_loop_for_ui
.PostDelayedTask(
730 message_loop_for_ui
.QuitClosure(),
731 base::TimeDelta::FromSeconds(
732 ThreadWatcherList::g_initialize_delay_seconds
));
733 message_loop_for_ui
.Run();
735 CheckState(false /* has_thread_watcher_list */,