Home | History | Annotate | Download | only in metrics
      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 }
    632