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/run_loop.h"
     14 #include "base/strings/string_number_conversions.h"
     15 #include "base/strings/string_split.h"
     16 #include "base/strings/string_tokenizer.h"
     17 #include "base/synchronization/condition_variable.h"
     18 #include "base/synchronization/lock.h"
     19 #include "base/threading/platform_thread.h"
     20 #include "base/time/time.h"
     21 #include "build/build_config.h"
     22 #include "chrome/browser/metrics/thread_watcher.h"
     23 #include "chrome/common/chrome_switches.h"
     24 #include "content/public/test/test_browser_thread.h"
     25 #include "testing/gtest/include/gtest/gtest.h"
     26 #include "testing/platform_test.h"
     27 
     28 using base::TimeDelta;
     29 using base::TimeTicks;
     30 using content::BrowserThread;
     31 
     32 enum State {
     33   INITIALIZED,        // Created ThreadWatch object.
     34   ACTIVATED,          // Thread watching activated.
     35   SENT_PING,          // Sent ping message to watched thread.
     36   RECEIVED_PONG,      // Received Pong message.
     37   DEACTIVATED,        // Thread watching de-activated.
     38 };
     39 
     40 enum WaitState {
     41   UNINITIALIZED,
     42   STARTED_WAITING,    // Start waiting for state_ to change to expected_state.
     43   STOPPED_WAITING,    // Done with the waiting.
     44   ALL_DONE,           // Done with waiting for STOPPED_WAITING.
     45 };
     46 
     47 enum CheckResponseState {
     48   UNKNOWN,
     49   SUCCESSFUL,         // CheckResponse was successful.
     50   FAILED,             // CheckResponse has failed.
     51 };
     52 
     53 // This class helps to track and manipulate thread state during tests. This
     54 // class also has utility method to simulate hanging of watched thread by making
     55 // the watched thread wait for a very long time by posting a task on watched
     56 // thread that keeps it busy. It also has an utility method to block running of
     57 // tests until ThreadWatcher object's post-condition state changes to an
     58 // expected state.
     59 class CustomThreadWatcher : public ThreadWatcher {
     60  public:
     61   base::Lock custom_lock_;
     62   base::ConditionVariable state_changed_;
     63   State thread_watcher_state_;
     64   WaitState wait_state_;
     65   CheckResponseState check_response_state_;
     66   uint64 ping_sent_;
     67   uint64 pong_received_;
     68   base::subtle::Atomic32 success_response_;
     69   base::subtle::Atomic32 failed_response_;
     70   base::TimeTicks saved_ping_time_;
     71   uint64 saved_ping_sequence_number_;
     72 
     73   CustomThreadWatcher(const BrowserThread::ID thread_id,
     74                       const std::string thread_name,
     75                       const TimeDelta& sleep_time,
     76                       const TimeDelta& unresponsive_time)
     77       : ThreadWatcher(WatchingParams(thread_id, thread_name, sleep_time,
     78                       unresponsive_time, ThreadWatcherList::kUnresponsiveCount,
     79                       true, ThreadWatcherList::kLiveThreadsThreshold)),
     80         state_changed_(&custom_lock_),
     81         thread_watcher_state_(INITIALIZED),
     82         wait_state_(UNINITIALIZED),
     83         check_response_state_(UNKNOWN),
     84         ping_sent_(0),
     85         pong_received_(0),
     86         success_response_(0),
     87         failed_response_(0),
     88         saved_ping_time_(base::TimeTicks::Now()),
     89         saved_ping_sequence_number_(0) {
     90   }
     91 
     92   State UpdateState(State new_state) {
     93     State old_state;
     94     {
     95       base::AutoLock auto_lock(custom_lock_);
     96       old_state = thread_watcher_state_;
     97       if (old_state != DEACTIVATED)
     98         thread_watcher_state_ = new_state;
     99       if (new_state == SENT_PING)
    100         ++ping_sent_;
    101       if (new_state == RECEIVED_PONG)
    102         ++pong_received_;
    103       saved_ping_time_ = ping_time();
    104       saved_ping_sequence_number_ = ping_sequence_number();
    105     }
    106     state_changed_.Broadcast();
    107     return old_state;
    108   }
    109 
    110   WaitState UpdateWaitState(WaitState new_state) {
    111     WaitState old_state;
    112     {
    113       base::AutoLock auto_lock(custom_lock_);
    114       old_state = wait_state_;
    115       wait_state_ = new_state;
    116     }
    117     state_changed_.Broadcast();
    118     return old_state;
    119   }
    120 
    121   virtual void ActivateThreadWatching() OVERRIDE {
    122     State old_state = UpdateState(ACTIVATED);
    123     EXPECT_EQ(old_state, INITIALIZED);
    124     ThreadWatcher::ActivateThreadWatching();
    125   }
    126 
    127   virtual void DeActivateThreadWatching() OVERRIDE {
    128     State old_state = UpdateState(DEACTIVATED);
    129     EXPECT_TRUE(old_state == ACTIVATED || old_state == SENT_PING ||
    130                 old_state == RECEIVED_PONG);
    131     ThreadWatcher::DeActivateThreadWatching();
    132   }
    133 
    134   virtual void PostPingMessage() OVERRIDE {
    135     State old_state = UpdateState(SENT_PING);
    136     EXPECT_TRUE(old_state == ACTIVATED || old_state == RECEIVED_PONG);
    137     ThreadWatcher::PostPingMessage();
    138   }
    139 
    140   virtual void OnPongMessage(uint64 ping_sequence_number) OVERRIDE {
    141     State old_state = UpdateState(RECEIVED_PONG);
    142     EXPECT_TRUE(old_state == SENT_PING || old_state == DEACTIVATED);
    143     ThreadWatcher::OnPongMessage(ping_sequence_number);
    144   }
    145 
    146   virtual void OnCheckResponsiveness(uint64 ping_sequence_number) OVERRIDE {
    147     ThreadWatcher::OnCheckResponsiveness(ping_sequence_number);
    148     {
    149       base::AutoLock auto_lock(custom_lock_);
    150       if (responsive_) {
    151         base::subtle::Release_Store(&success_response_,
    152             base::subtle::Acquire_Load(&success_response_) + 1);
    153         check_response_state_ = SUCCESSFUL;
    154       } else {
    155         base::subtle::Release_Store(&failed_response_,
    156             base::subtle::Acquire_Load(&failed_response_) + 1);
    157         check_response_state_ = FAILED;
    158       }
    159     }
    160     // Broadcast to indicate we have checked responsiveness of the thread that
    161     // is watched.
    162     state_changed_.Broadcast();
    163   }
    164 
    165   void WaitForWaitStateChange(TimeDelta wait_time, WaitState expected_state) {
    166     DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
    167     TimeTicks end_time = TimeTicks::Now() + wait_time;
    168     {
    169       base::AutoLock auto_lock(custom_lock_);
    170       while (wait_state_ != expected_state && TimeTicks::Now() < end_time)
    171         state_changed_.TimedWait(end_time - TimeTicks::Now());
    172     }
    173   }
    174 
    175   void VeryLongMethod(TimeDelta wait_time) {
    176     DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
    177     WaitForWaitStateChange(wait_time, STOPPED_WAITING);
    178     UpdateWaitState(ALL_DONE);
    179   }
    180 
    181   State WaitForStateChange(const TimeDelta& wait_time, State expected_state) {
    182     DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
    183     UpdateWaitState(STARTED_WAITING);
    184 
    185     State exit_state = INITIALIZED;
    186     // Keep the thread that is running the tests waiting until ThreadWatcher
    187     // object's state changes to the expected_state or until wait_time elapses.
    188     for (uint32 i = 0; i < unresponsive_threshold_; ++i) {
    189         TimeTicks end_time = TimeTicks::Now() + wait_time;
    190         {
    191           base::AutoLock auto_lock(custom_lock_);
    192           while (thread_watcher_state_ != expected_state &&
    193                  TimeTicks::Now() < end_time) {
    194             TimeDelta state_change_wait_time = end_time - TimeTicks::Now();
    195             state_changed_.TimedWait(state_change_wait_time);
    196           }
    197           // Capture the thread_watcher_state_ before it changes and return it
    198           // to the caller.
    199           exit_state = thread_watcher_state_;
    200           if (exit_state == expected_state)
    201             break;
    202         }
    203     }
    204     UpdateWaitState(STOPPED_WAITING);
    205     return exit_state;
    206   }
    207 
    208   CheckResponseState WaitForCheckResponse(const TimeDelta& wait_time,
    209                                           CheckResponseState expected_state) {
    210     DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
    211     UpdateWaitState(STARTED_WAITING);
    212 
    213     CheckResponseState exit_state = UNKNOWN;
    214     // Keep the thread that is running the tests waiting until ThreadWatcher
    215     // object's check_response_state_ changes to the expected_state or until
    216     // wait_time elapses.
    217     for (uint32 i = 0; i < unresponsive_threshold_; ++i) {
    218         TimeTicks end_time = TimeTicks::Now() + wait_time;
    219         {
    220           base::AutoLock auto_lock(custom_lock_);
    221           while (check_response_state_ != expected_state &&
    222                  TimeTicks::Now() < end_time) {
    223             TimeDelta state_change_wait_time = end_time - TimeTicks::Now();
    224             state_changed_.TimedWait(state_change_wait_time);
    225           }
    226           // Capture the check_response_state_ before it changes and return it
    227           // to the caller.
    228           exit_state = check_response_state_;
    229           if (exit_state == expected_state)
    230             break;
    231         }
    232     }
    233     UpdateWaitState(STOPPED_WAITING);
    234     return exit_state;
    235   }
    236 };
    237 
    238 class ThreadWatcherTest : public ::testing::Test {
    239  public:
    240   static const TimeDelta kSleepTime;
    241   static const TimeDelta kUnresponsiveTime;
    242   static const BrowserThread::ID io_thread_id;
    243   static const std::string io_thread_name;
    244   static const BrowserThread::ID db_thread_id;
    245   static const std::string db_thread_name;
    246   static const std::string crash_on_hang_seconds;
    247   static const std::string crash_on_hang_thread_names;
    248   static const std::string thread_names_and_live_threshold;
    249   static const std::string crash_on_hang_thread_data;
    250   CustomThreadWatcher* io_watcher_;
    251   CustomThreadWatcher* db_watcher_;
    252   ThreadWatcherList* thread_watcher_list_;
    253 
    254   ThreadWatcherTest()
    255       : setup_complete_(&lock_),
    256         initialized_(false) {
    257     db_thread_.reset(new content::TestBrowserThread(BrowserThread::DB));
    258     io_thread_.reset(new content::TestBrowserThread(BrowserThread::IO));
    259     watchdog_thread_.reset(new WatchDogThread());
    260     db_thread_->Start();
    261     io_thread_->Start();
    262     watchdog_thread_->Start();
    263 
    264     WatchDogThread::PostTask(
    265         FROM_HERE,
    266         base::Bind(&ThreadWatcherTest::SetUpObjects, base::Unretained(this)));
    267 
    268     WaitForSetUp(TimeDelta::FromMinutes(1));
    269   }
    270 
    271   void SetUpObjects() {
    272     DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
    273 
    274     // Setup the registry for thread watchers.
    275     thread_watcher_list_ = new ThreadWatcherList();
    276 
    277     // Create thread watcher object for the IO thread.
    278     io_watcher_ = new CustomThreadWatcher(io_thread_id, io_thread_name,
    279                                           kSleepTime, kUnresponsiveTime);
    280     EXPECT_EQ(io_watcher_, thread_watcher_list_->Find(io_thread_id));
    281 
    282     // Create thread watcher object for the DB thread.
    283     db_watcher_ = new CustomThreadWatcher(
    284         db_thread_id, db_thread_name, kSleepTime, kUnresponsiveTime);
    285     EXPECT_EQ(db_watcher_, thread_watcher_list_->Find(db_thread_id));
    286 
    287     {
    288       base::AutoLock lock(lock_);
    289       initialized_ = true;
    290     }
    291     setup_complete_.Signal();
    292   }
    293 
    294   void WaitForSetUp(TimeDelta wait_time) {
    295     DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
    296     TimeTicks end_time = TimeTicks::Now() + wait_time;
    297     {
    298       base::AutoLock auto_lock(lock_);
    299       while (!initialized_ && TimeTicks::Now() < end_time)
    300         setup_complete_.TimedWait(end_time - TimeTicks::Now());
    301     }
    302   }
    303 
    304   virtual ~ThreadWatcherTest() {
    305     ThreadWatcherList::DeleteAll();
    306     io_watcher_ = NULL;
    307     db_watcher_ = NULL;
    308     io_thread_.reset();
    309     db_thread_.reset();
    310     watchdog_thread_.reset();
    311     thread_watcher_list_ = NULL;
    312   }
    313 
    314  private:
    315   base::Lock lock_;
    316   base::ConditionVariable setup_complete_;
    317   bool initialized_;
    318   scoped_ptr<content::TestBrowserThread> db_thread_;
    319   scoped_ptr<content::TestBrowserThread> io_thread_;
    320   scoped_ptr<WatchDogThread> watchdog_thread_;
    321 };
    322 
    323 // Define static constants.
    324 const TimeDelta ThreadWatcherTest::kSleepTime =
    325     TimeDelta::FromMilliseconds(50);
    326 const TimeDelta ThreadWatcherTest::kUnresponsiveTime =
    327     TimeDelta::FromMilliseconds(500);
    328 const BrowserThread::ID ThreadWatcherTest::io_thread_id = BrowserThread::IO;
    329 const std::string ThreadWatcherTest::io_thread_name = "IO";
    330 const BrowserThread::ID ThreadWatcherTest::db_thread_id = BrowserThread::DB;
    331 const std::string ThreadWatcherTest::db_thread_name = "DB";
    332 const std::string ThreadWatcherTest::crash_on_hang_thread_names = "UI,IO";
    333 const std::string ThreadWatcherTest::thread_names_and_live_threshold =
    334     "UI:4,IO:4";
    335 const std::string ThreadWatcherTest::crash_on_hang_thread_data =
    336     "UI:5:12,IO:5:12,FILE:5:12";
    337 
    338 TEST_F(ThreadWatcherTest, ThreadNamesOnlyArgs) {
    339   // Setup command_line arguments.
    340   CommandLine command_line(CommandLine::NO_PROGRAM);
    341   command_line.AppendSwitchASCII(switches::kCrashOnHangThreads,
    342                                  crash_on_hang_thread_names);
    343 
    344   // Parse command_line arguments.
    345   ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads;
    346   uint32 unresponsive_threshold;
    347   ThreadWatcherList::ParseCommandLine(command_line,
    348                                       &unresponsive_threshold,
    349                                       &crash_on_hang_threads);
    350 
    351   // Verify the data.
    352   base::StringTokenizer tokens(crash_on_hang_thread_names, ",");
    353   std::vector<std::string> values;
    354   while (tokens.GetNext()) {
    355     const std::string& token = tokens.token();
    356     base::SplitString(token, ':', &values);
    357     std::string thread_name = values[0];
    358 
    359     ThreadWatcherList::CrashOnHangThreadMap::iterator it =
    360         crash_on_hang_threads.find(thread_name);
    361     bool crash_on_hang = (it != crash_on_hang_threads.end());
    362     EXPECT_TRUE(crash_on_hang);
    363     EXPECT_LT(0u, it->second.live_threads_threshold);
    364     EXPECT_LT(0u, it->second.unresponsive_threshold);
    365   }
    366 }
    367 
    368 TEST_F(ThreadWatcherTest, ThreadNamesAndLiveThresholdArgs) {
    369   // Setup command_line arguments.
    370   CommandLine command_line(CommandLine::NO_PROGRAM);
    371   command_line.AppendSwitchASCII(switches::kCrashOnHangThreads,
    372                                  thread_names_and_live_threshold);
    373 
    374   // Parse command_line arguments.
    375   ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads;
    376   uint32 unresponsive_threshold;
    377   ThreadWatcherList::ParseCommandLine(command_line,
    378                                       &unresponsive_threshold,
    379                                       &crash_on_hang_threads);
    380 
    381   // Verify the data.
    382   base::StringTokenizer tokens(thread_names_and_live_threshold, ",");
    383   std::vector<std::string> values;
    384   while (tokens.GetNext()) {
    385     const std::string& token = tokens.token();
    386     base::SplitString(token, ':', &values);
    387     std::string thread_name = values[0];
    388 
    389     ThreadWatcherList::CrashOnHangThreadMap::iterator it =
    390         crash_on_hang_threads.find(thread_name);
    391     bool crash_on_hang = (it != crash_on_hang_threads.end());
    392     EXPECT_TRUE(crash_on_hang);
    393     EXPECT_EQ(4u, it->second.live_threads_threshold);
    394     EXPECT_LT(0u, it->second.unresponsive_threshold);
    395   }
    396 }
    397 
    398 TEST_F(ThreadWatcherTest, CrashOnHangThreadsAllArgs) {
    399   // Setup command_line arguments.
    400   CommandLine command_line(CommandLine::NO_PROGRAM);
    401   command_line.AppendSwitchASCII(switches::kCrashOnHangThreads,
    402                                  crash_on_hang_thread_data);
    403 
    404   // Parse command_line arguments.
    405   ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads;
    406   uint32 unresponsive_threshold;
    407   ThreadWatcherList::ParseCommandLine(command_line,
    408                                       &unresponsive_threshold,
    409                                       &crash_on_hang_threads);
    410 
    411   // Verify the data.
    412   base::StringTokenizer tokens(crash_on_hang_thread_data, ",");
    413   std::vector<std::string> values;
    414   while (tokens.GetNext()) {
    415     const std::string& token = tokens.token();
    416     base::SplitString(token, ':', &values);
    417     std::string thread_name = values[0];
    418 
    419     ThreadWatcherList::CrashOnHangThreadMap::iterator it =
    420         crash_on_hang_threads.find(thread_name);
    421 
    422     bool crash_on_hang = (it != crash_on_hang_threads.end());
    423     EXPECT_TRUE(crash_on_hang);
    424 
    425     uint32 crash_live_threads_threshold = it->second.live_threads_threshold;
    426     EXPECT_EQ(5u, crash_live_threads_threshold);
    427 
    428     uint32 crash_unresponsive_threshold = it->second.unresponsive_threshold;
    429     uint32 crash_on_unresponsive_seconds =
    430         ThreadWatcherList::kUnresponsiveSeconds * crash_unresponsive_threshold;
    431     EXPECT_EQ(12u, crash_on_unresponsive_seconds);
    432   }
    433 }
    434 
    435 // Test registration. When thread_watcher_list_ goes out of scope after
    436 // TearDown, all thread watcher objects will be deleted.
    437 TEST_F(ThreadWatcherTest, Registration) {
    438   // Check ThreadWatcher object has all correct parameters.
    439   EXPECT_EQ(io_thread_id, io_watcher_->thread_id());
    440   EXPECT_EQ(io_thread_name, io_watcher_->thread_name());
    441   EXPECT_EQ(kSleepTime, io_watcher_->sleep_time());
    442   EXPECT_EQ(kUnresponsiveTime, io_watcher_->unresponsive_time());
    443   EXPECT_FALSE(io_watcher_->active());
    444 
    445   // Check ThreadWatcher object of watched DB thread has correct data.
    446   EXPECT_EQ(db_thread_id, db_watcher_->thread_id());
    447   EXPECT_EQ(db_thread_name, db_watcher_->thread_name());
    448   EXPECT_EQ(kSleepTime, db_watcher_->sleep_time());
    449   EXPECT_EQ(kUnresponsiveTime, db_watcher_->unresponsive_time());
    450   EXPECT_FALSE(db_watcher_->active());
    451 }
    452 
    453 // Test ActivateThreadWatching and DeActivateThreadWatching of IO thread. This
    454 // method also checks that pong message was sent by the watched thread and pong
    455 // message was received by the WatchDogThread. It also checks that
    456 // OnCheckResponsiveness has verified the ping-pong mechanism and the watched
    457 // thread is not hung.
    458 TEST_F(ThreadWatcherTest, ThreadResponding) {
    459   TimeTicks time_before_ping = TimeTicks::Now();
    460   // Activate watching IO thread.
    461   WatchDogThread::PostTask(
    462       FROM_HERE,
    463       base::Bind(&ThreadWatcher::ActivateThreadWatching,
    464                  base::Unretained(io_watcher_)));
    465 
    466   // Activate would have started ping/pong messaging. Expect atleast one
    467   // ping/pong messaging sequence to happen.
    468   io_watcher_->WaitForStateChange(kSleepTime + TimeDelta::FromMinutes(1),
    469                                   RECEIVED_PONG);
    470   EXPECT_GT(io_watcher_->ping_sent_, static_cast<uint64>(0));
    471   EXPECT_GT(io_watcher_->pong_received_, static_cast<uint64>(0));
    472   EXPECT_TRUE(io_watcher_->active());
    473   EXPECT_GE(io_watcher_->saved_ping_time_, time_before_ping);
    474   EXPECT_GE(io_watcher_->saved_ping_sequence_number_, static_cast<uint64>(0));
    475 
    476   // Verify watched thread is responding with ping/pong messaging.
    477   io_watcher_->WaitForCheckResponse(
    478       kUnresponsiveTime + TimeDelta::FromMinutes(1), SUCCESSFUL);
    479   EXPECT_GT(base::subtle::NoBarrier_Load(&(io_watcher_->success_response_)),
    480       static_cast<base::subtle::Atomic32>(0));
    481   EXPECT_EQ(base::subtle::NoBarrier_Load(&(io_watcher_->failed_response_)),
    482       static_cast<base::subtle::Atomic32>(0));
    483 
    484   // DeActivate thread watching for shutdown.
    485   WatchDogThread::PostTask(
    486       FROM_HERE,
    487       base::Bind(&ThreadWatcher::DeActivateThreadWatching,
    488       base::Unretained(io_watcher_)));
    489 }
    490 
    491 // This test posts a task on watched thread that takes very long time (this is
    492 // to simulate hanging of watched thread). It then checks for
    493 // OnCheckResponsiveness raising an alert (OnCheckResponsiveness returns false
    494 // if the watched thread is not responding).
    495 TEST_F(ThreadWatcherTest, ThreadNotResponding) {
    496   // Simulate hanging of watched thread by making the watched thread wait for a
    497   // very long time by posting a task on watched thread that keeps it busy.
    498   // It is safe to use base::Unretained because test is waiting for the method
    499   // to finish.
    500   BrowserThread::PostTask(
    501       io_thread_id,
    502       FROM_HERE,
    503       base::Bind(&CustomThreadWatcher::VeryLongMethod,
    504                  base::Unretained(io_watcher_),
    505                  kUnresponsiveTime * 10));
    506 
    507   // Activate thread watching.
    508   WatchDogThread::PostTask(
    509       FROM_HERE,
    510       base::Bind(&ThreadWatcher::ActivateThreadWatching,
    511                  base::Unretained(io_watcher_)));
    512 
    513   // Verify watched thread is not responding for ping messages.
    514   io_watcher_->WaitForCheckResponse(
    515       kUnresponsiveTime + TimeDelta::FromMinutes(1), FAILED);
    516   EXPECT_EQ(base::subtle::NoBarrier_Load(&(io_watcher_->success_response_)),
    517       static_cast<base::subtle::Atomic32>(0));
    518   EXPECT_GT(base::subtle::NoBarrier_Load(&(io_watcher_->failed_response_)),
    519       static_cast<base::subtle::Atomic32>(0));
    520 
    521   // DeActivate thread watching for shutdown.
    522   WatchDogThread::PostTask(
    523       FROM_HERE,
    524       base::Bind(&ThreadWatcher::DeActivateThreadWatching,
    525                  base::Unretained(io_watcher_)));
    526 
    527   // Wait for the io_watcher_'s VeryLongMethod to finish.
    528   io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE);
    529 }
    530 
    531 // Test watching of multiple threads with all threads not responding.
    532 TEST_F(ThreadWatcherTest, MultipleThreadsResponding) {
    533   // Check for DB thread to perform ping/pong messaging.
    534   WatchDogThread::PostTask(
    535       FROM_HERE,
    536       base::Bind(&ThreadWatcher::ActivateThreadWatching,
    537                  base::Unretained(db_watcher_)));
    538 
    539   // Check for IO thread to perform ping/pong messaging.
    540   WatchDogThread::PostTask(
    541       FROM_HERE,
    542       base::Bind(&ThreadWatcher::ActivateThreadWatching,
    543                  base::Unretained(io_watcher_)));
    544 
    545   // Verify DB thread is responding with ping/pong messaging.
    546   db_watcher_->WaitForCheckResponse(
    547       kUnresponsiveTime + TimeDelta::FromMinutes(1), SUCCESSFUL);
    548   EXPECT_GT(db_watcher_->ping_sent_, static_cast<uint64>(0));
    549   EXPECT_GT(db_watcher_->pong_received_, static_cast<uint64>(0));
    550   EXPECT_GE(db_watcher_->ping_sequence_number_, static_cast<uint64>(0));
    551   EXPECT_GT(base::subtle::NoBarrier_Load(&(db_watcher_->success_response_)),
    552       static_cast<base::subtle::Atomic32>(0));
    553   EXPECT_EQ(base::subtle::NoBarrier_Load(&(db_watcher_->failed_response_)),
    554       static_cast<base::subtle::Atomic32>(0));
    555 
    556   // Verify IO thread is responding with ping/pong messaging.
    557   io_watcher_->WaitForCheckResponse(
    558       kUnresponsiveTime + TimeDelta::FromMinutes(1), SUCCESSFUL);
    559   EXPECT_GT(io_watcher_->ping_sent_, static_cast<uint64>(0));
    560   EXPECT_GT(io_watcher_->pong_received_, static_cast<uint64>(0));
    561   EXPECT_GE(io_watcher_->ping_sequence_number_, static_cast<uint64>(0));
    562   EXPECT_GT(base::subtle::NoBarrier_Load(&(io_watcher_->success_response_)),
    563       static_cast<base::subtle::Atomic32>(0));
    564   EXPECT_EQ(base::subtle::NoBarrier_Load(&(io_watcher_->failed_response_)),
    565       static_cast<base::subtle::Atomic32>(0));
    566 
    567   // DeActivate thread watching for shutdown.
    568   WatchDogThread::PostTask(
    569       FROM_HERE,
    570       base::Bind(&ThreadWatcher::DeActivateThreadWatching,
    571                  base::Unretained(io_watcher_)));
    572 
    573   WatchDogThread::PostTask(
    574       FROM_HERE,
    575       base::Bind(&ThreadWatcher::DeActivateThreadWatching,
    576                  base::Unretained(db_watcher_)));
    577 }
    578 
    579 // Test watching of multiple threads with one of the threads not responding.
    580 TEST_F(ThreadWatcherTest, MultipleThreadsNotResponding) {
    581   // Simulate hanging of watched thread by making the watched thread wait for a
    582   // very long time by posting a task on watched thread that keeps it busy.
    583   // It is safe ot use base::Unretained because test is waiting for the method
    584   // to finish.
    585   BrowserThread::PostTask(
    586       io_thread_id,
    587       FROM_HERE,
    588       base::Bind(&CustomThreadWatcher::VeryLongMethod,
    589                  base::Unretained(io_watcher_),
    590                  kUnresponsiveTime * 10));
    591 
    592   // Activate watching of DB thread.
    593   WatchDogThread::PostTask(
    594       FROM_HERE,
    595       base::Bind(&ThreadWatcher::ActivateThreadWatching,
    596                  base::Unretained(db_watcher_)));
    597 
    598   // Activate watching of IO thread.
    599   WatchDogThread::PostTask(
    600       FROM_HERE,
    601       base::Bind(&ThreadWatcher::ActivateThreadWatching,
    602                  base::Unretained(io_watcher_)));
    603 
    604   // Verify DB thread is responding with ping/pong messaging.
    605   db_watcher_->WaitForCheckResponse(
    606       kUnresponsiveTime + TimeDelta::FromMinutes(1), SUCCESSFUL);
    607   EXPECT_GT(base::subtle::NoBarrier_Load(&(db_watcher_->success_response_)),
    608       static_cast<base::subtle::Atomic32>(0));
    609   EXPECT_EQ(base::subtle::NoBarrier_Load(&(db_watcher_->failed_response_)),
    610       static_cast<base::subtle::Atomic32>(0));
    611 
    612   // Verify IO thread is not responding for ping messages.
    613   io_watcher_->WaitForCheckResponse(
    614       kUnresponsiveTime + TimeDelta::FromMinutes(1), FAILED);
    615   EXPECT_EQ(base::subtle::NoBarrier_Load(&(io_watcher_->success_response_)),
    616       static_cast<base::subtle::Atomic32>(0));
    617   EXPECT_GT(base::subtle::NoBarrier_Load(&(io_watcher_->failed_response_)),
    618       static_cast<base::subtle::Atomic32>(0));
    619 
    620   // DeActivate thread watching for shutdown.
    621   WatchDogThread::PostTask(
    622       FROM_HERE,
    623       base::Bind(&ThreadWatcher::DeActivateThreadWatching,
    624                  base::Unretained(io_watcher_)));
    625   WatchDogThread::PostTask(
    626       FROM_HERE,
    627       base::Bind(&ThreadWatcher::DeActivateThreadWatching,
    628                  base::Unretained(db_watcher_)));
    629 
    630   // Wait for the io_watcher_'s VeryLongMethod to finish.
    631   io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE);
    632 }
    633 
    634 class ThreadWatcherListTest : public ::testing::Test {
    635  protected:
    636   ThreadWatcherListTest()
    637       : done_(&lock_),
    638         state_available_(false),
    639         has_thread_watcher_list_(false),
    640         stopped_(false) {
    641   }
    642 
    643   void ReadStateOnWatchDogThread() {
    644     CHECK(WatchDogThread::CurrentlyOnWatchDogThread());
    645     {
    646       base::AutoLock auto_lock(lock_);
    647       has_thread_watcher_list_ =
    648           ThreadWatcherList::g_thread_watcher_list_ != NULL;
    649       stopped_ = ThreadWatcherList::g_stopped_;
    650       state_available_ = true;
    651     }
    652     done_.Signal();
    653   }
    654 
    655   void CheckState(bool has_thread_watcher_list,
    656                   bool stopped,
    657                   const char* const msg) {
    658     CHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
    659     {
    660       base::AutoLock auto_lock(lock_);
    661       state_available_ = false;
    662     }
    663 
    664     WatchDogThread::PostTask(
    665         FROM_HERE,
    666         base::Bind(&ThreadWatcherListTest::ReadStateOnWatchDogThread,
    667                    base::Unretained(this)));
    668     {
    669       base::AutoLock auto_lock(lock_);
    670       while (!state_available_)
    671         done_.Wait();
    672 
    673       EXPECT_EQ(has_thread_watcher_list, has_thread_watcher_list_) << msg;
    674       EXPECT_EQ(stopped, stopped_) << msg;
    675     }
    676   }
    677 
    678   base::Lock lock_;
    679   base::ConditionVariable done_;
    680 
    681   bool state_available_;
    682   bool has_thread_watcher_list_;
    683   bool stopped_;
    684 };
    685 
    686 TEST_F(ThreadWatcherListTest, Restart) {
    687   ThreadWatcherList::g_initialize_delay_seconds = 1;
    688 
    689   base::MessageLoopForUI message_loop_for_ui;
    690   content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop_for_ui);
    691 
    692   scoped_ptr<WatchDogThread> watchdog_thread_(new WatchDogThread());
    693   watchdog_thread_->Start();
    694 
    695   // See http://crbug.com/347887.
    696   // StartWatchingAll() will PostDelayedTask to create g_thread_watcher_list_,
    697   // whilst StopWatchingAll() will just PostTask to destroy it.
    698   // Ensure that when Stop is called, Start will NOT create
    699   // g_thread_watcher_list_ later on.
    700   ThreadWatcherList::StartWatchingAll(*CommandLine::ForCurrentProcess());
    701   ThreadWatcherList::StopWatchingAll();
    702   message_loop_for_ui.PostDelayedTask(
    703       FROM_HERE,
    704       message_loop_for_ui.QuitClosure(),
    705       base::TimeDelta::FromSeconds(
    706           ThreadWatcherList::g_initialize_delay_seconds));
    707   message_loop_for_ui.Run();
    708 
    709   CheckState(false /* has_thread_watcher_list */,
    710              true /* stopped */,
    711              "Start / Stopped");
    712 
    713   // Proceed with just |StartWatchingAll| and ensure it'll be started.
    714   ThreadWatcherList::StartWatchingAll(*CommandLine::ForCurrentProcess());
    715   message_loop_for_ui.PostDelayedTask(
    716       FROM_HERE,
    717       message_loop_for_ui.QuitClosure(),
    718       base::TimeDelta::FromSeconds(
    719           ThreadWatcherList::g_initialize_delay_seconds + 1));
    720   message_loop_for_ui.Run();
    721 
    722   CheckState(true /* has_thread_watcher_list */,
    723              false /* stopped */,
    724              "Started");
    725 
    726   // Finally, StopWatchingAll() must stop.
    727   ThreadWatcherList::StopWatchingAll();
    728   message_loop_for_ui.PostDelayedTask(
    729       FROM_HERE,
    730       message_loop_for_ui.QuitClosure(),
    731       base::TimeDelta::FromSeconds(
    732           ThreadWatcherList::g_initialize_delay_seconds));
    733   message_loop_for_ui.Run();
    734 
    735   CheckState(false /* has_thread_watcher_list */,
    736              true /* stopped */,
    737              "Stopped");
    738 }
    739