Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / metrics / thread_watcher_unittest.cc
blob4b799e9c07f051ba64a18869e5625706d8f834bd
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.
5 #include <math.h>
7 #include "base/basictypes.h"
8 #include "base/bind.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;
31 enum State {
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.
39 enum WaitState {
40 UNINITIALIZED,
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 {
47 UNKNOWN,
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
57 // expected state.
58 class CustomThreadWatcher : public ThreadWatcher {
59 public:
60 base::Lock custom_lock_;
61 base::ConditionVariable state_changed_;
62 State thread_watcher_state_;
63 WaitState wait_state_;
64 CheckResponseState check_response_state_;
65 uint64 ping_sent_;
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),
83 ping_sent_(0),
84 pong_received_(0),
85 success_response_(0),
86 failed_response_(0),
87 saved_ping_time_(base::TimeTicks::Now()),
88 saved_ping_sequence_number_(0) {
91 State UpdateState(State new_state) {
92 State old_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)
99 ++ping_sent_;
100 if (new_state == RECEIVED_PONG)
101 ++pong_received_;
102 saved_ping_time_ = ping_time();
103 saved_ping_sequence_number_ = ping_sequence_number();
105 state_changed_.Broadcast();
106 return old_state;
109 WaitState UpdateWaitState(WaitState new_state) {
110 WaitState old_state;
112 base::AutoLock auto_lock(custom_lock_);
113 old_state = wait_state_;
114 wait_state_ = new_state;
116 state_changed_.Broadcast();
117 return old_state;
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_);
149 if (responsive_) {
150 base::subtle::Release_Store(&success_response_,
151 base::subtle::Acquire_Load(&success_response_) + 1);
152 check_response_state_ = SUCCESSFUL;
153 } else {
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
160 // is watched.
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
197 // to the caller.
198 exit_state = thread_watcher_state_;
199 if (exit_state == expected_state)
200 break;
203 UpdateWaitState(STOPPED_WAITING);
204 return exit_state;
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
226 // to the caller.
227 exit_state = check_response_state_;
228 if (exit_state == expected_state)
229 break;
232 UpdateWaitState(STOPPED_WAITING);
233 return exit_state;
237 class ThreadWatcherTest : public ::testing::Test {
238 public:
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_;
253 ThreadWatcherTest()
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());
259 db_thread_->Start();
260 io_thread_->Start();
261 watchdog_thread_->Start();
263 WatchDogThread::PostTask(
264 FROM_HERE,
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_);
288 initialized_ = true;
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();
305 io_watcher_ = NULL;
306 db_watcher_ = NULL;
307 io_thread_.reset();
308 db_thread_.reset();
309 watchdog_thread_.reset();
310 thread_watcher_list_ = NULL;
313 private:
314 base::Lock lock_;
315 base::ConditionVariable setup_complete_;
316 bool initialized_;
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 =
333 "UI:4,IO:4";
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);
350 // Verify the data.
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);
380 // Verify the data.
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);
410 // Verify the data.
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(
461 FROM_HERE,
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),
468 RECEIVED_PONG);
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(
485 FROM_HERE,
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
498 // to finish.
499 BrowserThread::PostTask(
500 io_thread_id,
501 FROM_HERE,
502 base::Bind(&CustomThreadWatcher::VeryLongMethod,
503 base::Unretained(io_watcher_),
504 kUnresponsiveTime * 10));
506 // Activate thread watching.
507 WatchDogThread::PostTask(
508 FROM_HERE,
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(
522 FROM_HERE,
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(
534 FROM_HERE,
535 base::Bind(&ThreadWatcher::ActivateThreadWatching,
536 base::Unretained(db_watcher_)));
538 // Check for IO thread to perform ping/pong messaging.
539 WatchDogThread::PostTask(
540 FROM_HERE,
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(
568 FROM_HERE,
569 base::Bind(&ThreadWatcher::DeActivateThreadWatching,
570 base::Unretained(io_watcher_)));
572 WatchDogThread::PostTask(
573 FROM_HERE,
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
583 // to finish.
584 BrowserThread::PostTask(
585 io_thread_id,
586 FROM_HERE,
587 base::Bind(&CustomThreadWatcher::VeryLongMethod,
588 base::Unretained(io_watcher_),
589 kUnresponsiveTime * 10));
591 // Activate watching of DB thread.
592 WatchDogThread::PostTask(
593 FROM_HERE,
594 base::Bind(&ThreadWatcher::ActivateThreadWatching,
595 base::Unretained(db_watcher_)));
597 // Activate watching of IO thread.
598 WatchDogThread::PostTask(
599 FROM_HERE,
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(
621 FROM_HERE,
622 base::Bind(&ThreadWatcher::DeActivateThreadWatching,
623 base::Unretained(io_watcher_)));
624 WatchDogThread::PostTask(
625 FROM_HERE,
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);