- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / metrics / thread_watcher_unittest.cc
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.
4
5 #include <math.h>
6
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"
26
27 using base::TimeDelta;
28 using base::TimeTicks;
29 using content::BrowserThread;
30
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.
37 };
38
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.
44 };
45
46 enum CheckResponseState {
47   UNKNOWN,
48   SUCCESSFUL,         // CheckResponse was successful.
49   FAILED,             // CheckResponse has failed.
50 };
51
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_;
71
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) {
89   }
90
91   State UpdateState(State new_state) {
92     State old_state;
93     {
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();
104     }
105     state_changed_.Broadcast();
106     return old_state;
107   }
108
109   WaitState UpdateWaitState(WaitState new_state) {
110     WaitState old_state;
111     {
112       base::AutoLock auto_lock(custom_lock_);
113       old_state = wait_state_;
114       wait_state_ = new_state;
115     }
116     state_changed_.Broadcast();
117     return old_state;
118   }
119
120   virtual void ActivateThreadWatching() OVERRIDE {
121     State old_state = UpdateState(ACTIVATED);
122     EXPECT_EQ(old_state, INITIALIZED);
123     ThreadWatcher::ActivateThreadWatching();
124   }
125
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();
131   }
132
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();
137   }
138
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);
143   }
144
145   virtual void OnCheckResponsiveness(uint64 ping_sequence_number) OVERRIDE {
146     ThreadWatcher::OnCheckResponsiveness(ping_sequence_number);
147     {
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;
157       }
158     }
159     // Broadcast to indicate we have checked responsiveness of the thread that
160     // is watched.
161     state_changed_.Broadcast();
162   }
163
164   void WaitForWaitStateChange(TimeDelta wait_time, WaitState expected_state) {
165     DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
166     TimeTicks end_time = TimeTicks::Now() + wait_time;
167     {
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());
171     }
172   }
173
174   void VeryLongMethod(TimeDelta wait_time) {
175     DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
176     WaitForWaitStateChange(wait_time, STOPPED_WAITING);
177     UpdateWaitState(ALL_DONE);
178   }
179
180   State WaitForStateChange(const TimeDelta& wait_time, State expected_state) {
181     DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
182     UpdateWaitState(STARTED_WAITING);
183
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;
189         {
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);
195           }
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;
201         }
202     }
203     UpdateWaitState(STOPPED_WAITING);
204     return exit_state;
205   }
206
207   CheckResponseState WaitForCheckResponse(const TimeDelta& wait_time,
208                                           CheckResponseState expected_state) {
209     DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
210     UpdateWaitState(STARTED_WAITING);
211
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;
218         {
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);
224           }
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;
230         }
231     }
232     UpdateWaitState(STOPPED_WAITING);
233     return exit_state;
234   }
235 };
236
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_;
252
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();
262
263     WatchDogThread::PostTask(
264         FROM_HERE,
265         base::Bind(&ThreadWatcherTest::SetUpObjects, base::Unretained(this)));
266
267     WaitForSetUp(TimeDelta::FromMinutes(1));
268   }
269
270   void SetUpObjects() {
271     DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
272
273     // Setup the registry for thread watchers.
274     thread_watcher_list_ = new ThreadWatcherList();
275
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));
280
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));
285
286     {
287       base::AutoLock lock(lock_);
288       initialized_ = true;
289     }
290     setup_complete_.Signal();
291   }
292
293   void WaitForSetUp(TimeDelta wait_time) {
294     DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
295     TimeTicks end_time = TimeTicks::Now() + wait_time;
296     {
297       base::AutoLock auto_lock(lock_);
298       while (!initialized_ && TimeTicks::Now() < end_time)
299         setup_complete_.TimedWait(end_time - TimeTicks::Now());
300     }
301   }
302
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;
311   }
312
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_;
320 };
321
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";
336
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);
342
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);
349
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];
357
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);
364   }
365 }
366
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);
372
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);
379
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];
387
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);
394   }
395 }
396
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);
402
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);
409
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];
417
418     ThreadWatcherList::CrashOnHangThreadMap::iterator it =
419         crash_on_hang_threads.find(thread_name);
420
421     bool crash_on_hang = (it != crash_on_hang_threads.end());
422     EXPECT_TRUE(crash_on_hang);
423
424     uint32 crash_live_threads_threshold = it->second.live_threads_threshold;
425     EXPECT_EQ(5u, crash_live_threads_threshold);
426
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);
431   }
432 }
433
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());
443
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());
450 }
451
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_)));
464
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));
474
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));
482
483   // DeActivate thread watching for shutdown.
484   WatchDogThread::PostTask(
485       FROM_HERE,
486       base::Bind(&ThreadWatcher::DeActivateThreadWatching,
487       base::Unretained(io_watcher_)));
488 }
489
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));
505
506   // Activate thread watching.
507   WatchDogThread::PostTask(
508       FROM_HERE,
509       base::Bind(&ThreadWatcher::ActivateThreadWatching,
510                  base::Unretained(io_watcher_)));
511
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));
519
520   // DeActivate thread watching for shutdown.
521   WatchDogThread::PostTask(
522       FROM_HERE,
523       base::Bind(&ThreadWatcher::DeActivateThreadWatching,
524                  base::Unretained(io_watcher_)));
525
526   // Wait for the io_watcher_'s VeryLongMethod to finish.
527   io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE);
528 }
529
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_)));
537
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_)));
543
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));
554
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));
565
566   // DeActivate thread watching for shutdown.
567   WatchDogThread::PostTask(
568       FROM_HERE,
569       base::Bind(&ThreadWatcher::DeActivateThreadWatching,
570                  base::Unretained(io_watcher_)));
571
572   WatchDogThread::PostTask(
573       FROM_HERE,
574       base::Bind(&ThreadWatcher::DeActivateThreadWatching,
575                  base::Unretained(db_watcher_)));
576 }
577
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));
590
591   // Activate watching of DB thread.
592   WatchDogThread::PostTask(
593       FROM_HERE,
594       base::Bind(&ThreadWatcher::ActivateThreadWatching,
595                  base::Unretained(db_watcher_)));
596
597   // Activate watching of IO thread.
598   WatchDogThread::PostTask(
599       FROM_HERE,
600       base::Bind(&ThreadWatcher::ActivateThreadWatching,
601                  base::Unretained(io_watcher_)));
602
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));
610
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));
618
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_)));
628
629   // Wait for the io_watcher_'s VeryLongMethod to finish.
630   io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE);
631 }