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/strings/string_number_conversions.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/string_tokenizer.h"
16 #include "base/synchronization/condition_variable.h"
17 #include "base/synchronization/lock.h"
18 #include "base/threading/platform_thread.h"
19 #include "base/time/time.h"
20 #include "build/build_config.h"
21 #include "chrome/browser/metrics/thread_watcher.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "content/public/test/test_browser_thread.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "testing/platform_test.h"
27 using base::TimeDelta
;
28 using base::TimeTicks
;
29 using content::BrowserThread
;
32 INITIALIZED
, // Created ThreadWatch object.
33 ACTIVATED
, // Thread watching activated.
34 SENT_PING
, // Sent ping message to watched thread.
35 RECEIVED_PONG
, // Received Pong message.
36 DEACTIVATED
, // Thread watching de-activated.
41 STARTED_WAITING
, // Start waiting for state_ to change to expected_state.
42 STOPPED_WAITING
, // Done with the waiting.
43 ALL_DONE
, // Done with waiting for STOPPED_WAITING.
46 enum CheckResponseState
{
48 SUCCESSFUL
, // CheckResponse was successful.
49 FAILED
, // CheckResponse has failed.
52 // This class helps to track and manipulate thread state during tests. This
53 // class also has utility method to simulate hanging of watched thread by making
54 // the watched thread wait for a very long time by posting a task on watched
55 // thread that keeps it busy. It also has an utility method to block running of
56 // tests until ThreadWatcher object's post-condition state changes to an
58 class CustomThreadWatcher
: public ThreadWatcher
{
60 base::Lock custom_lock_
;
61 base::ConditionVariable state_changed_
;
62 State thread_watcher_state_
;
63 WaitState wait_state_
;
64 CheckResponseState check_response_state_
;
66 uint64 pong_received_
;
67 base::subtle::Atomic32 success_response_
;
68 base::subtle::Atomic32 failed_response_
;
69 base::TimeTicks saved_ping_time_
;
70 uint64 saved_ping_sequence_number_
;
72 CustomThreadWatcher(const BrowserThread::ID thread_id
,
73 const std::string thread_name
,
74 const TimeDelta
& sleep_time
,
75 const TimeDelta
& unresponsive_time
)
76 : ThreadWatcher(WatchingParams(thread_id
, thread_name
, sleep_time
,
77 unresponsive_time
, ThreadWatcherList::kUnresponsiveCount
,
78 true, ThreadWatcherList::kLiveThreadsThreshold
)),
79 state_changed_(&custom_lock_
),
80 thread_watcher_state_(INITIALIZED
),
81 wait_state_(UNINITIALIZED
),
82 check_response_state_(UNKNOWN
),
87 saved_ping_time_(base::TimeTicks::Now()),
88 saved_ping_sequence_number_(0) {
91 State
UpdateState(State new_state
) {
94 base::AutoLock
auto_lock(custom_lock_
);
95 old_state
= thread_watcher_state_
;
96 if (old_state
!= DEACTIVATED
)
97 thread_watcher_state_
= new_state
;
98 if (new_state
== SENT_PING
)
100 if (new_state
== RECEIVED_PONG
)
102 saved_ping_time_
= ping_time();
103 saved_ping_sequence_number_
= ping_sequence_number();
105 state_changed_
.Broadcast();
109 WaitState
UpdateWaitState(WaitState new_state
) {
112 base::AutoLock
auto_lock(custom_lock_
);
113 old_state
= wait_state_
;
114 wait_state_
= new_state
;
116 state_changed_
.Broadcast();
120 virtual void ActivateThreadWatching() OVERRIDE
{
121 State old_state
= UpdateState(ACTIVATED
);
122 EXPECT_EQ(old_state
, INITIALIZED
);
123 ThreadWatcher::ActivateThreadWatching();
126 virtual void DeActivateThreadWatching() OVERRIDE
{
127 State old_state
= UpdateState(DEACTIVATED
);
128 EXPECT_TRUE(old_state
== ACTIVATED
|| old_state
== SENT_PING
||
129 old_state
== RECEIVED_PONG
);
130 ThreadWatcher::DeActivateThreadWatching();
133 virtual void PostPingMessage() OVERRIDE
{
134 State old_state
= UpdateState(SENT_PING
);
135 EXPECT_TRUE(old_state
== ACTIVATED
|| old_state
== RECEIVED_PONG
);
136 ThreadWatcher::PostPingMessage();
139 virtual void OnPongMessage(uint64 ping_sequence_number
) OVERRIDE
{
140 State old_state
= UpdateState(RECEIVED_PONG
);
141 EXPECT_TRUE(old_state
== SENT_PING
|| old_state
== DEACTIVATED
);
142 ThreadWatcher::OnPongMessage(ping_sequence_number
);
145 virtual void OnCheckResponsiveness(uint64 ping_sequence_number
) OVERRIDE
{
146 ThreadWatcher::OnCheckResponsiveness(ping_sequence_number
);
148 base::AutoLock
auto_lock(custom_lock_
);
150 base::subtle::Release_Store(&success_response_
,
151 base::subtle::Acquire_Load(&success_response_
) + 1);
152 check_response_state_
= SUCCESSFUL
;
154 base::subtle::Release_Store(&failed_response_
,
155 base::subtle::Acquire_Load(&failed_response_
) + 1);
156 check_response_state_
= FAILED
;
159 // Broadcast to indicate we have checked responsiveness of the thread that
161 state_changed_
.Broadcast();
164 void WaitForWaitStateChange(TimeDelta wait_time
, WaitState expected_state
) {
165 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
166 TimeTicks end_time
= TimeTicks::Now() + wait_time
;
168 base::AutoLock
auto_lock(custom_lock_
);
169 while (wait_state_
!= expected_state
&& TimeTicks::Now() < end_time
)
170 state_changed_
.TimedWait(end_time
- TimeTicks::Now());
174 void VeryLongMethod(TimeDelta wait_time
) {
175 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
176 WaitForWaitStateChange(wait_time
, STOPPED_WAITING
);
177 UpdateWaitState(ALL_DONE
);
180 State
WaitForStateChange(const TimeDelta
& wait_time
, State expected_state
) {
181 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
182 UpdateWaitState(STARTED_WAITING
);
184 State exit_state
= INITIALIZED
;
185 // Keep the thread that is running the tests waiting until ThreadWatcher
186 // object's state changes to the expected_state or until wait_time elapses.
187 for (uint32 i
= 0; i
< unresponsive_threshold_
; ++i
) {
188 TimeTicks end_time
= TimeTicks::Now() + wait_time
;
190 base::AutoLock
auto_lock(custom_lock_
);
191 while (thread_watcher_state_
!= expected_state
&&
192 TimeTicks::Now() < end_time
) {
193 TimeDelta state_change_wait_time
= end_time
- TimeTicks::Now();
194 state_changed_
.TimedWait(state_change_wait_time
);
196 // Capture the thread_watcher_state_ before it changes and return it
198 exit_state
= thread_watcher_state_
;
199 if (exit_state
== expected_state
)
203 UpdateWaitState(STOPPED_WAITING
);
207 CheckResponseState
WaitForCheckResponse(const TimeDelta
& wait_time
,
208 CheckResponseState expected_state
) {
209 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
210 UpdateWaitState(STARTED_WAITING
);
212 CheckResponseState exit_state
= UNKNOWN
;
213 // Keep the thread that is running the tests waiting until ThreadWatcher
214 // object's check_response_state_ changes to the expected_state or until
215 // wait_time elapses.
216 for (uint32 i
= 0; i
< unresponsive_threshold_
; ++i
) {
217 TimeTicks end_time
= TimeTicks::Now() + wait_time
;
219 base::AutoLock
auto_lock(custom_lock_
);
220 while (check_response_state_
!= expected_state
&&
221 TimeTicks::Now() < end_time
) {
222 TimeDelta state_change_wait_time
= end_time
- TimeTicks::Now();
223 state_changed_
.TimedWait(state_change_wait_time
);
225 // Capture the check_response_state_ before it changes and return it
227 exit_state
= check_response_state_
;
228 if (exit_state
== expected_state
)
232 UpdateWaitState(STOPPED_WAITING
);
237 class ThreadWatcherTest
: public ::testing::Test
{
239 static const TimeDelta kSleepTime
;
240 static const TimeDelta kUnresponsiveTime
;
241 static const BrowserThread::ID io_thread_id
;
242 static const std::string io_thread_name
;
243 static const BrowserThread::ID db_thread_id
;
244 static const std::string db_thread_name
;
245 static const std::string crash_on_hang_seconds
;
246 static const std::string crash_on_hang_thread_names
;
247 static const std::string thread_names_and_live_threshold
;
248 static const std::string crash_on_hang_thread_data
;
249 CustomThreadWatcher
* io_watcher_
;
250 CustomThreadWatcher
* db_watcher_
;
251 ThreadWatcherList
* thread_watcher_list_
;
254 : setup_complete_(&lock_
),
255 initialized_(false) {
256 db_thread_
.reset(new content::TestBrowserThread(BrowserThread::DB
));
257 io_thread_
.reset(new content::TestBrowserThread(BrowserThread::IO
));
258 watchdog_thread_
.reset(new WatchDogThread());
261 watchdog_thread_
->Start();
263 WatchDogThread::PostTask(
265 base::Bind(&ThreadWatcherTest::SetUpObjects
, base::Unretained(this)));
267 WaitForSetUp(TimeDelta::FromMinutes(1));
270 void SetUpObjects() {
271 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
273 // Setup the registry for thread watchers.
274 thread_watcher_list_
= new ThreadWatcherList();
276 // Create thread watcher object for the IO thread.
277 io_watcher_
= new CustomThreadWatcher(io_thread_id
, io_thread_name
,
278 kSleepTime
, kUnresponsiveTime
);
279 EXPECT_EQ(io_watcher_
, thread_watcher_list_
->Find(io_thread_id
));
281 // Create thread watcher object for the DB thread.
282 db_watcher_
= new CustomThreadWatcher(
283 db_thread_id
, db_thread_name
, kSleepTime
, kUnresponsiveTime
);
284 EXPECT_EQ(db_watcher_
, thread_watcher_list_
->Find(db_thread_id
));
287 base::AutoLock
lock(lock_
);
290 setup_complete_
.Signal();
293 void WaitForSetUp(TimeDelta wait_time
) {
294 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
295 TimeTicks end_time
= TimeTicks::Now() + wait_time
;
297 base::AutoLock
auto_lock(lock_
);
298 while (!initialized_
&& TimeTicks::Now() < end_time
)
299 setup_complete_
.TimedWait(end_time
- TimeTicks::Now());
303 virtual ~ThreadWatcherTest() {
304 ThreadWatcherList::DeleteAll();
309 watchdog_thread_
.reset();
310 thread_watcher_list_
= NULL
;
315 base::ConditionVariable setup_complete_
;
317 scoped_ptr
<content::TestBrowserThread
> db_thread_
;
318 scoped_ptr
<content::TestBrowserThread
> io_thread_
;
319 scoped_ptr
<WatchDogThread
> watchdog_thread_
;
322 // Define static constants.
323 const TimeDelta
ThreadWatcherTest::kSleepTime
=
324 TimeDelta::FromMilliseconds(50);
325 const TimeDelta
ThreadWatcherTest::kUnresponsiveTime
=
326 TimeDelta::FromMilliseconds(500);
327 const BrowserThread::ID
ThreadWatcherTest::io_thread_id
= BrowserThread::IO
;
328 const std::string
ThreadWatcherTest::io_thread_name
= "IO";
329 const BrowserThread::ID
ThreadWatcherTest::db_thread_id
= BrowserThread::DB
;
330 const std::string
ThreadWatcherTest::db_thread_name
= "DB";
331 const std::string
ThreadWatcherTest::crash_on_hang_thread_names
= "UI,IO";
332 const std::string
ThreadWatcherTest::thread_names_and_live_threshold
=
334 const std::string
ThreadWatcherTest::crash_on_hang_thread_data
=
335 "UI:5:12,IO:5:12,FILE:5:12";
337 TEST_F(ThreadWatcherTest
, ThreadNamesOnlyArgs
) {
338 // Setup command_line arguments.
339 CommandLine
command_line(CommandLine::NO_PROGRAM
);
340 command_line
.AppendSwitchASCII(switches::kCrashOnHangThreads
,
341 crash_on_hang_thread_names
);
343 // Parse command_line arguments.
344 ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads
;
345 uint32 unresponsive_threshold
;
346 ThreadWatcherList::ParseCommandLine(command_line
,
347 &unresponsive_threshold
,
348 &crash_on_hang_threads
);
351 base::StringTokenizer
tokens(crash_on_hang_thread_names
, ",");
352 std::vector
<std::string
> values
;
353 while (tokens
.GetNext()) {
354 const std::string
& token
= tokens
.token();
355 base::SplitString(token
, ':', &values
);
356 std::string thread_name
= values
[0];
358 ThreadWatcherList::CrashOnHangThreadMap::iterator it
=
359 crash_on_hang_threads
.find(thread_name
);
360 bool crash_on_hang
= (it
!= crash_on_hang_threads
.end());
361 EXPECT_TRUE(crash_on_hang
);
362 EXPECT_LT(0u, it
->second
.live_threads_threshold
);
363 EXPECT_LT(0u, it
->second
.unresponsive_threshold
);
367 TEST_F(ThreadWatcherTest
, ThreadNamesAndLiveThresholdArgs
) {
368 // Setup command_line arguments.
369 CommandLine
command_line(CommandLine::NO_PROGRAM
);
370 command_line
.AppendSwitchASCII(switches::kCrashOnHangThreads
,
371 thread_names_and_live_threshold
);
373 // Parse command_line arguments.
374 ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads
;
375 uint32 unresponsive_threshold
;
376 ThreadWatcherList::ParseCommandLine(command_line
,
377 &unresponsive_threshold
,
378 &crash_on_hang_threads
);
381 base::StringTokenizer
tokens(thread_names_and_live_threshold
, ",");
382 std::vector
<std::string
> values
;
383 while (tokens
.GetNext()) {
384 const std::string
& token
= tokens
.token();
385 base::SplitString(token
, ':', &values
);
386 std::string thread_name
= values
[0];
388 ThreadWatcherList::CrashOnHangThreadMap::iterator it
=
389 crash_on_hang_threads
.find(thread_name
);
390 bool crash_on_hang
= (it
!= crash_on_hang_threads
.end());
391 EXPECT_TRUE(crash_on_hang
);
392 EXPECT_EQ(4u, it
->second
.live_threads_threshold
);
393 EXPECT_LT(0u, it
->second
.unresponsive_threshold
);
397 TEST_F(ThreadWatcherTest
, CrashOnHangThreadsAllArgs
) {
398 // Setup command_line arguments.
399 CommandLine
command_line(CommandLine::NO_PROGRAM
);
400 command_line
.AppendSwitchASCII(switches::kCrashOnHangThreads
,
401 crash_on_hang_thread_data
);
403 // Parse command_line arguments.
404 ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads
;
405 uint32 unresponsive_threshold
;
406 ThreadWatcherList::ParseCommandLine(command_line
,
407 &unresponsive_threshold
,
408 &crash_on_hang_threads
);
411 base::StringTokenizer
tokens(crash_on_hang_thread_data
, ",");
412 std::vector
<std::string
> values
;
413 while (tokens
.GetNext()) {
414 const std::string
& token
= tokens
.token();
415 base::SplitString(token
, ':', &values
);
416 std::string thread_name
= values
[0];
418 ThreadWatcherList::CrashOnHangThreadMap::iterator it
=
419 crash_on_hang_threads
.find(thread_name
);
421 bool crash_on_hang
= (it
!= crash_on_hang_threads
.end());
422 EXPECT_TRUE(crash_on_hang
);
424 uint32 crash_live_threads_threshold
= it
->second
.live_threads_threshold
;
425 EXPECT_EQ(5u, crash_live_threads_threshold
);
427 uint32 crash_unresponsive_threshold
= it
->second
.unresponsive_threshold
;
428 uint32 crash_on_unresponsive_seconds
=
429 ThreadWatcherList::kUnresponsiveSeconds
* crash_unresponsive_threshold
;
430 EXPECT_EQ(12u, crash_on_unresponsive_seconds
);
434 // Test registration. When thread_watcher_list_ goes out of scope after
435 // TearDown, all thread watcher objects will be deleted.
436 TEST_F(ThreadWatcherTest
, Registration
) {
437 // Check ThreadWatcher object has all correct parameters.
438 EXPECT_EQ(io_thread_id
, io_watcher_
->thread_id());
439 EXPECT_EQ(io_thread_name
, io_watcher_
->thread_name());
440 EXPECT_EQ(kSleepTime
, io_watcher_
->sleep_time());
441 EXPECT_EQ(kUnresponsiveTime
, io_watcher_
->unresponsive_time());
442 EXPECT_FALSE(io_watcher_
->active());
444 // Check ThreadWatcher object of watched DB thread has correct data.
445 EXPECT_EQ(db_thread_id
, db_watcher_
->thread_id());
446 EXPECT_EQ(db_thread_name
, db_watcher_
->thread_name());
447 EXPECT_EQ(kSleepTime
, db_watcher_
->sleep_time());
448 EXPECT_EQ(kUnresponsiveTime
, db_watcher_
->unresponsive_time());
449 EXPECT_FALSE(db_watcher_
->active());
452 // Test ActivateThreadWatching and DeActivateThreadWatching of IO thread. This
453 // method also checks that pong message was sent by the watched thread and pong
454 // message was received by the WatchDogThread. It also checks that
455 // OnCheckResponsiveness has verified the ping-pong mechanism and the watched
456 // thread is not hung.
457 TEST_F(ThreadWatcherTest
, ThreadResponding
) {
458 TimeTicks time_before_ping
= TimeTicks::Now();
459 // Activate watching IO thread.
460 WatchDogThread::PostTask(
462 base::Bind(&ThreadWatcher::ActivateThreadWatching
,
463 base::Unretained(io_watcher_
)));
465 // Activate would have started ping/pong messaging. Expect atleast one
466 // ping/pong messaging sequence to happen.
467 io_watcher_
->WaitForStateChange(kSleepTime
+ TimeDelta::FromMinutes(1),
469 EXPECT_GT(io_watcher_
->ping_sent_
, static_cast<uint64
>(0));
470 EXPECT_GT(io_watcher_
->pong_received_
, static_cast<uint64
>(0));
471 EXPECT_TRUE(io_watcher_
->active());
472 EXPECT_GE(io_watcher_
->saved_ping_time_
, time_before_ping
);
473 EXPECT_GE(io_watcher_
->saved_ping_sequence_number_
, static_cast<uint64
>(0));
475 // Verify watched thread is responding with ping/pong messaging.
476 io_watcher_
->WaitForCheckResponse(
477 kUnresponsiveTime
+ TimeDelta::FromMinutes(1), SUCCESSFUL
);
478 EXPECT_GT(base::subtle::NoBarrier_Load(&(io_watcher_
->success_response_
)),
479 static_cast<base::subtle::Atomic32
>(0));
480 EXPECT_EQ(base::subtle::NoBarrier_Load(&(io_watcher_
->failed_response_
)),
481 static_cast<base::subtle::Atomic32
>(0));
483 // DeActivate thread watching for shutdown.
484 WatchDogThread::PostTask(
486 base::Bind(&ThreadWatcher::DeActivateThreadWatching
,
487 base::Unretained(io_watcher_
)));
490 // This test posts a task on watched thread that takes very long time (this is
491 // to simulate hanging of watched thread). It then checks for
492 // OnCheckResponsiveness raising an alert (OnCheckResponsiveness returns false
493 // if the watched thread is not responding).
494 TEST_F(ThreadWatcherTest
, ThreadNotResponding
) {
495 // Simulate hanging of watched thread by making the watched thread wait for a
496 // very long time by posting a task on watched thread that keeps it busy.
497 // It is safe to use base::Unretained because test is waiting for the method
499 BrowserThread::PostTask(
502 base::Bind(&CustomThreadWatcher::VeryLongMethod
,
503 base::Unretained(io_watcher_
),
504 kUnresponsiveTime
* 10));
506 // Activate thread watching.
507 WatchDogThread::PostTask(
509 base::Bind(&ThreadWatcher::ActivateThreadWatching
,
510 base::Unretained(io_watcher_
)));
512 // Verify watched thread is not responding for ping messages.
513 io_watcher_
->WaitForCheckResponse(
514 kUnresponsiveTime
+ TimeDelta::FromMinutes(1), FAILED
);
515 EXPECT_EQ(base::subtle::NoBarrier_Load(&(io_watcher_
->success_response_
)),
516 static_cast<base::subtle::Atomic32
>(0));
517 EXPECT_GT(base::subtle::NoBarrier_Load(&(io_watcher_
->failed_response_
)),
518 static_cast<base::subtle::Atomic32
>(0));
520 // DeActivate thread watching for shutdown.
521 WatchDogThread::PostTask(
523 base::Bind(&ThreadWatcher::DeActivateThreadWatching
,
524 base::Unretained(io_watcher_
)));
526 // Wait for the io_watcher_'s VeryLongMethod to finish.
527 io_watcher_
->WaitForWaitStateChange(kUnresponsiveTime
* 10, ALL_DONE
);
530 // Test watching of multiple threads with all threads not responding.
531 TEST_F(ThreadWatcherTest
, MultipleThreadsResponding
) {
532 // Check for DB thread to perform ping/pong messaging.
533 WatchDogThread::PostTask(
535 base::Bind(&ThreadWatcher::ActivateThreadWatching
,
536 base::Unretained(db_watcher_
)));
538 // Check for IO thread to perform ping/pong messaging.
539 WatchDogThread::PostTask(
541 base::Bind(&ThreadWatcher::ActivateThreadWatching
,
542 base::Unretained(io_watcher_
)));
544 // Verify DB thread is responding with ping/pong messaging.
545 db_watcher_
->WaitForCheckResponse(
546 kUnresponsiveTime
+ TimeDelta::FromMinutes(1), SUCCESSFUL
);
547 EXPECT_GT(db_watcher_
->ping_sent_
, static_cast<uint64
>(0));
548 EXPECT_GT(db_watcher_
->pong_received_
, static_cast<uint64
>(0));
549 EXPECT_GE(db_watcher_
->ping_sequence_number_
, static_cast<uint64
>(0));
550 EXPECT_GT(base::subtle::NoBarrier_Load(&(db_watcher_
->success_response_
)),
551 static_cast<base::subtle::Atomic32
>(0));
552 EXPECT_EQ(base::subtle::NoBarrier_Load(&(db_watcher_
->failed_response_
)),
553 static_cast<base::subtle::Atomic32
>(0));
555 // Verify IO thread is responding with ping/pong messaging.
556 io_watcher_
->WaitForCheckResponse(
557 kUnresponsiveTime
+ TimeDelta::FromMinutes(1), SUCCESSFUL
);
558 EXPECT_GT(io_watcher_
->ping_sent_
, static_cast<uint64
>(0));
559 EXPECT_GT(io_watcher_
->pong_received_
, static_cast<uint64
>(0));
560 EXPECT_GE(io_watcher_
->ping_sequence_number_
, static_cast<uint64
>(0));
561 EXPECT_GT(base::subtle::NoBarrier_Load(&(io_watcher_
->success_response_
)),
562 static_cast<base::subtle::Atomic32
>(0));
563 EXPECT_EQ(base::subtle::NoBarrier_Load(&(io_watcher_
->failed_response_
)),
564 static_cast<base::subtle::Atomic32
>(0));
566 // DeActivate thread watching for shutdown.
567 WatchDogThread::PostTask(
569 base::Bind(&ThreadWatcher::DeActivateThreadWatching
,
570 base::Unretained(io_watcher_
)));
572 WatchDogThread::PostTask(
574 base::Bind(&ThreadWatcher::DeActivateThreadWatching
,
575 base::Unretained(db_watcher_
)));
578 // Test watching of multiple threads with one of the threads not responding.
579 TEST_F(ThreadWatcherTest
, MultipleThreadsNotResponding
) {
580 // Simulate hanging of watched thread by making the watched thread wait for a
581 // very long time by posting a task on watched thread that keeps it busy.
582 // It is safe ot use base::Unretained because test is waiting for the method
584 BrowserThread::PostTask(
587 base::Bind(&CustomThreadWatcher::VeryLongMethod
,
588 base::Unretained(io_watcher_
),
589 kUnresponsiveTime
* 10));
591 // Activate watching of DB thread.
592 WatchDogThread::PostTask(
594 base::Bind(&ThreadWatcher::ActivateThreadWatching
,
595 base::Unretained(db_watcher_
)));
597 // Activate watching of IO thread.
598 WatchDogThread::PostTask(
600 base::Bind(&ThreadWatcher::ActivateThreadWatching
,
601 base::Unretained(io_watcher_
)));
603 // Verify DB thread is responding with ping/pong messaging.
604 db_watcher_
->WaitForCheckResponse(
605 kUnresponsiveTime
+ TimeDelta::FromMinutes(1), SUCCESSFUL
);
606 EXPECT_GT(base::subtle::NoBarrier_Load(&(db_watcher_
->success_response_
)),
607 static_cast<base::subtle::Atomic32
>(0));
608 EXPECT_EQ(base::subtle::NoBarrier_Load(&(db_watcher_
->failed_response_
)),
609 static_cast<base::subtle::Atomic32
>(0));
611 // Verify IO thread is not responding for ping messages.
612 io_watcher_
->WaitForCheckResponse(
613 kUnresponsiveTime
+ TimeDelta::FromMinutes(1), FAILED
);
614 EXPECT_EQ(base::subtle::NoBarrier_Load(&(io_watcher_
->success_response_
)),
615 static_cast<base::subtle::Atomic32
>(0));
616 EXPECT_GT(base::subtle::NoBarrier_Load(&(io_watcher_
->failed_response_
)),
617 static_cast<base::subtle::Atomic32
>(0));
619 // DeActivate thread watching for shutdown.
620 WatchDogThread::PostTask(
622 base::Bind(&ThreadWatcher::DeActivateThreadWatching
,
623 base::Unretained(io_watcher_
)));
624 WatchDogThread::PostTask(
626 base::Bind(&ThreadWatcher::DeActivateThreadWatching
,
627 base::Unretained(db_watcher_
)));
629 // Wait for the io_watcher_'s VeryLongMethod to finish.
630 io_watcher_
->WaitForWaitStateChange(kUnresponsiveTime
* 10, ALL_DONE
);