1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be
3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file.
4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/basictypes.h"
6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/logging.h"
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/message_loop.h"
9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/message_loop_proxy.h"
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/synchronization/condition_variable.h"
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/synchronization/lock.h"
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/threading/platform_thread.h"
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/time.h"
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "build/build_config.h"
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/metrics/thread_watcher.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "testing/gtest/include/gtest/gtest.h"
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "testing/platform_test.h"
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing base::TimeDelta;
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing base::TimeTicks;
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenenum State {
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  INITIALIZED,        // Created ThreadWatch object.
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ACTIVATED,          // Thread watching activated.
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SENT_PING,          // Sent ping message to watched thread.
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  RECEIVED_PONG,      // Received Pong message.
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DEACTIVATED,        // Thread watching de-activated.
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenenum WaitState {
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  UNINITIALIZED,
32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  STARTED_WAITING,    // Start waiting for state_ to change to expected_state.
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  STOPPED_WAITING,    // Done with the waiting.
34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ALL_DONE,           // Done with waiting for STOPPED_WAITING.
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenenum CheckResponseState {
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  UNKNOWN,
39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SUCCESSFUL,         // CheckResponse was successful.
40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FAILED,             // CheckResponse has failed.
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// This class helps to track and manipulate thread state during tests. This
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// class also has utility method to simulate hanging of watched thread by making
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// the watched thread wait for a very long time by posting a task on watched
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// thread that keeps it busy. It also has an utility method to block running of
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// tests until ThreadWatcher object's post-condition state changes to an
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// expected state.
49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass CustomThreadWatcher : public ThreadWatcher {
50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public:
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  base::Lock custom_lock_;
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  base::ConditionVariable state_changed_;
53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  State thread_watcher_state_;
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WaitState wait_state_;
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CheckResponseState check_response_state_;
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  uint64 ping_sent_;
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  uint64 pong_received_;
58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  uint64 success_response_;
59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  uint64 failed_response_;
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  base::TimeTicks saved_ping_time_;
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  uint64 saved_ping_sequence_number_;
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CustomThreadWatcher(const BrowserThread::ID thread_id,
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      const std::string thread_name,
65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      const TimeDelta& sleep_time,
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                      const TimeDelta& unresponsive_time)
67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      : ThreadWatcher(thread_id, thread_name, sleep_time, unresponsive_time),
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        state_changed_(&custom_lock_),
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        thread_watcher_state_(INITIALIZED),
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        wait_state_(UNINITIALIZED),
71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        check_response_state_(UNKNOWN),
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ping_sent_(0),
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        pong_received_(0),
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        success_response_(0),
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        failed_response_(0),
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        saved_ping_time_(base::TimeTicks::Now()),
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        saved_ping_sequence_number_(0) {
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  State UpdateState(State new_state) {
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    State old_state;
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    {
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      base::AutoLock auto_lock(custom_lock_);
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      old_state = thread_watcher_state_;
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (old_state != DEACTIVATED)
86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        thread_watcher_state_ = new_state;
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (new_state == SENT_PING)
88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ++ping_sent_;
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (new_state == RECEIVED_PONG)
90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ++pong_received_;
91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      saved_ping_time_ = ping_time();
92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      saved_ping_sequence_number_ = ping_sequence_number();
93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    state_changed_.Broadcast();
95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return old_state;
96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WaitState UpdateWaitState(WaitState new_state) {
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    WaitState old_state;
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    {
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      base::AutoLock auto_lock(custom_lock_);
102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      old_state = wait_state_;
103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      wait_state_ = new_state;
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    state_changed_.Broadcast();
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return old_state;
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void ActivateThreadWatching() {
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    State old_state = UpdateState(ACTIVATED);
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    EXPECT_EQ(old_state, INITIALIZED);
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ThreadWatcher::ActivateThreadWatching();
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void DeActivateThreadWatching() {
116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    State old_state = UpdateState(DEACTIVATED);
117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    EXPECT_TRUE(old_state == ACTIVATED || old_state == SENT_PING ||
118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                old_state == RECEIVED_PONG);
119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ThreadWatcher::DeActivateThreadWatching();
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void PostPingMessage() {
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    State old_state = UpdateState(SENT_PING);
124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    EXPECT_TRUE(old_state == ACTIVATED || old_state == RECEIVED_PONG);
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ThreadWatcher::PostPingMessage();
126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void OnPongMessage(uint64 ping_sequence_number) {
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    State old_state = UpdateState(RECEIVED_PONG);
130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    EXPECT_TRUE(old_state == SENT_PING || old_state == DEACTIVATED);
131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ThreadWatcher::OnPongMessage(ping_sequence_number);
132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool OnCheckResponsiveness(uint64 ping_sequence_number) {
135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    bool responsive =
136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ThreadWatcher::OnCheckResponsiveness(ping_sequence_number);
137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    {
138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      base::AutoLock auto_lock(custom_lock_);
139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (responsive) {
140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ++success_response_;
141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        check_response_state_ = SUCCESSFUL;
142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      } else {
143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        ++failed_response_;
144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        check_response_state_ = FAILED;
145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Broadcast to indicate we have checked responsiveness of the thread that
148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // is watched.
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    state_changed_.Broadcast();
150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return responsive;
151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void WaitForWaitStateChange(TimeDelta wait_time, WaitState expected_state) {
154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    TimeTicks end_time = TimeTicks::Now() + wait_time;
156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    {
157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      base::AutoLock auto_lock(custom_lock_);
158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      while (wait_state_ != expected_state && TimeTicks::Now() < end_time)
159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        state_changed_.TimedWait(end_time - TimeTicks::Now());
160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void VeryLongMethod(TimeDelta wait_time) {
164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    WaitForWaitStateChange(wait_time, STOPPED_WAITING);
166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    UpdateWaitState(ALL_DONE);
167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  State WaitForStateChange(const TimeDelta& wait_time, State expected_state) {
170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    UpdateWaitState(STARTED_WAITING);
172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    State exit_state;
174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Keep the thread that is running the tests waiting until ThreadWatcher
175dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // object's state changes to the expected_state or until wait_time elapses.
176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    for (int i = 0; i < 3; ++i) {
177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        TimeTicks end_time = TimeTicks::Now() + wait_time;
178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        {
179dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          base::AutoLock auto_lock(custom_lock_);
180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          while (thread_watcher_state_ != expected_state &&
181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                 TimeTicks::Now() < end_time) {
182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            TimeDelta state_change_wait_time = end_time - TimeTicks::Now();
183dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            state_changed_.TimedWait(state_change_wait_time);
184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          }
185dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          // Capture the thread_watcher_state_ before it changes and return it
186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          // to the caller.
187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          exit_state = thread_watcher_state_;
188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          if (exit_state == expected_state)
189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            break;
190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        }
191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    UpdateWaitState(STOPPED_WAITING);
193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return exit_state;
194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CheckResponseState WaitForCheckResponse(const TimeDelta& wait_time,
197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                          CheckResponseState expected_state) {
198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    UpdateWaitState(STARTED_WAITING);
200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
201dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CheckResponseState exit_state;
202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Keep the thread that is running the tests waiting until ThreadWatcher
203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // object's check_response_state_ changes to the expected_state or until
204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // wait_time elapses.
205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    for (int i = 0; i < 3; ++i) {
206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        TimeTicks end_time = TimeTicks::Now() + wait_time;
207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        {
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          base::AutoLock auto_lock(custom_lock_);
209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          while (check_response_state_ != expected_state &&
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                 TimeTicks::Now() < end_time) {
211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            TimeDelta state_change_wait_time = end_time - TimeTicks::Now();
212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            state_changed_.TimedWait(state_change_wait_time);
213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          }
214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          // Capture the check_response_state_ before it changes and return it
215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          // to the caller.
216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          exit_state = check_response_state_;
217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          if (exit_state == expected_state)
218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            break;
219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        }
220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    UpdateWaitState(STOPPED_WAITING);
222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return exit_state;
223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
226dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenDISABLE_RUNNABLE_METHOD_REFCOUNT(CustomThreadWatcher);
227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass ThreadWatcherTest : public ::testing::Test {
229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public:
230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static const TimeDelta kSleepTime;
231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static const TimeDelta kUnresponsiveTime;
232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static const BrowserThread::ID io_thread_id;
233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static const std::string io_thread_name;
234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static const BrowserThread::ID webkit_thread_id;
235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static const std::string webkit_thread_name;
236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CustomThreadWatcher* io_watcher_;
237dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CustomThreadWatcher* webkit_watcher_;
238dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ThreadWatcherTest() {
240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    webkit_thread_.reset(new BrowserThread(BrowserThread::WEBKIT));
241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    io_thread_.reset(new BrowserThread(BrowserThread::IO));
242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    watchdog_thread_.reset(new WatchDogThread());
243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    webkit_thread_->Start();
244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    io_thread_->Start();
245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    watchdog_thread_->Start();
246dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Setup the registry for thread watchers.
248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    thread_watcher_list_ = new ThreadWatcherList();
249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Create thread watcher object for the IO thread.
251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    io_watcher_ = new CustomThreadWatcher(io_thread_id, io_thread_name,
252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                          kSleepTime, kUnresponsiveTime);
253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Create thread watcher object for the WEBKIT thread.
255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    webkit_watcher_ = new CustomThreadWatcher(
256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        webkit_thread_id, webkit_thread_name, kSleepTime, kUnresponsiveTime);
257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ~ThreadWatcherTest() {
260dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    ThreadWatcherList::StopWatchingAll();
261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    io_watcher_ = NULL;
262dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    webkit_watcher_ = NULL;
263dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    io_thread_.reset();
264dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    webkit_thread_.reset();
265dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    watchdog_thread_.reset();
266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    delete thread_watcher_list_;
267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
268dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
269dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen private:
270dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<BrowserThread> webkit_thread_;
271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<BrowserThread> io_thread_;
272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_ptr<WatchDogThread> watchdog_thread_;
273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ThreadWatcherList* thread_watcher_list_;
274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen};
275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
276dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Define static constants.
277dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst TimeDelta ThreadWatcherTest::kSleepTime =
278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    TimeDelta::FromMilliseconds(50);
279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst TimeDelta ThreadWatcherTest::kUnresponsiveTime =
280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    TimeDelta::FromMilliseconds(500);
281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst BrowserThread::ID ThreadWatcherTest::io_thread_id = BrowserThread::IO;
282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst std::string ThreadWatcherTest::io_thread_name = "IO";
283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst BrowserThread::ID ThreadWatcherTest::webkit_thread_id =
284dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    BrowserThread::WEBKIT;
285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst std::string ThreadWatcherTest::webkit_thread_name = "WEBKIT";
286dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Test registration. When thread_watcher_list_ goes out of scope after
288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// TearDown, all thread watcher objects will be deleted.
289dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ThreadWatcherTest, Registration) {
290dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(io_watcher_, ThreadWatcherList::Find(io_thread_id));
291dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(webkit_watcher_, ThreadWatcherList::Find(webkit_thread_id));
292dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Check ThreadWatcher object has all correct parameters.
294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(io_thread_id, io_watcher_->thread_id());
295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(io_thread_name, io_watcher_->thread_name());
296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(kSleepTime, io_watcher_->sleep_time());
297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(kUnresponsiveTime, io_watcher_->unresponsive_time());
298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_FALSE(io_watcher_->active());
299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Check ThreadWatcher object of watched WEBKIT thread has correct data.
301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(webkit_thread_id, webkit_watcher_->thread_id());
302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(webkit_thread_name, webkit_watcher_->thread_name());
303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(kSleepTime, webkit_watcher_->sleep_time());
304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(kUnresponsiveTime, webkit_watcher_->unresponsive_time());
305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_FALSE(webkit_watcher_->active());
306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Test ActivateThreadWatching and DeActivateThreadWatching of IO thread. This
309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// method also checks that pong message was sent by the watched thread and pong
310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// message was received by the WatchDogThread. It also checks that
311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// OnCheckResponsiveness has verified the ping-pong mechanism and the watched
312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// thread is not hung.
313dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ThreadWatcherTest, ThreadResponding) {
314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TimeTicks time_before_ping = TimeTicks::Now();
315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Activate watching IO thread.
316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WatchDogThread::PostTask(
317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(io_watcher_, &ThreadWatcher::ActivateThreadWatching));
319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Activate would have started ping/pong messaging. Expect atleast one
321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // ping/pong messaging sequence to happen.
322dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  io_watcher_->WaitForStateChange(kSleepTime + TimeDelta::FromMinutes(1),
323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                  RECEIVED_PONG);
324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GT(io_watcher_->ping_sent_, static_cast<uint64>(0));
325dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GT(io_watcher_->pong_received_, static_cast<uint64>(0));
326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_TRUE(io_watcher_->active());
327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GE(io_watcher_->saved_ping_time_, time_before_ping);
328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GE(io_watcher_->saved_ping_sequence_number_, static_cast<uint64>(0));
329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Verify watched thread is responding with ping/pong messaging.
331dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  io_watcher_->WaitForCheckResponse(
332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      kUnresponsiveTime + TimeDelta::FromMinutes(1), SUCCESSFUL);
333dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GT(io_watcher_->success_response_, static_cast<uint64>(0));
334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(io_watcher_->failed_response_, static_cast<uint64>(0));
335dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
336dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // DeActivate thread watching for shutdown.
337dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WatchDogThread::PostTask(
338dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
339dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(io_watcher_, &ThreadWatcher::DeActivateThreadWatching));
340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// This test posts a task on watched thread that takes very long time (this is
343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// to simulate hanging of watched thread). It then checks for
344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// OnCheckResponsiveness raising an alert (OnCheckResponsiveness returns false
345dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// if the watched thread is not responding).
346dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ThreadWatcherTest, ThreadNotResponding) {
347dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Simulate hanging of watched thread by making the watched thread wait for a
348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // very long time by posting a task on watched thread that keeps it busy.
349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  BrowserThread::PostTask(
350dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      io_thread_id,
351dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
352dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(
353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          io_watcher_,
354dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          &CustomThreadWatcher::VeryLongMethod,
355dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          kUnresponsiveTime * 10));
356dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
357dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Activate thread watching.
358dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WatchDogThread::PostTask(
359dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
360dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(io_watcher_, &ThreadWatcher::ActivateThreadWatching));
361dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
362dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Verify watched thread is not responding for ping messages.
363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  io_watcher_->WaitForCheckResponse(
364dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      kUnresponsiveTime + TimeDelta::FromMinutes(1), FAILED);
365dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(io_watcher_->success_response_, static_cast<uint64>(0));
366dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GT(io_watcher_->failed_response_, static_cast<uint64>(0));
367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
368dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // DeActivate thread watching for shutdown.
369dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WatchDogThread::PostTask(
370dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
371dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(io_watcher_, &ThreadWatcher::DeActivateThreadWatching));
372dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
373dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Wait for the io_watcher_'s VeryLongMethod to finish.
374dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE);
375dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
376dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Test watching of multiple threads with all threads not responding.
378dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ThreadWatcherTest, MultipleThreadsResponding) {
379dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Check for WEBKIT thread to perform ping/pong messaging.
380dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WatchDogThread::PostTask(
381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(
383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          webkit_watcher_, &ThreadWatcher::ActivateThreadWatching));
384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
385dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Check for IO thread to perform ping/pong messaging.
386dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WatchDogThread::PostTask(
387dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(io_watcher_, &ThreadWatcher::ActivateThreadWatching));
389dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
390dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Verify WEBKIT thread is responding with ping/pong messaging.
391dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  webkit_watcher_->WaitForCheckResponse(
392dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      kUnresponsiveTime + TimeDelta::FromMinutes(1), SUCCESSFUL);
393dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GT(webkit_watcher_->ping_sent_, static_cast<uint64>(0));
394dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GT(webkit_watcher_->pong_received_, static_cast<uint64>(0));
395dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GE(webkit_watcher_->ping_sequence_number_, static_cast<uint64>(0));
396dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GT(webkit_watcher_->success_response_, static_cast<uint64>(0));
397dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(webkit_watcher_->failed_response_, static_cast<uint64>(0));
398dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
399dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Verify IO thread is responding with ping/pong messaging.
400dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  io_watcher_->WaitForCheckResponse(
401dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      kUnresponsiveTime + TimeDelta::FromMinutes(1), SUCCESSFUL);
402dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GT(io_watcher_->ping_sent_, static_cast<uint64>(0));
403dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GT(io_watcher_->pong_received_, static_cast<uint64>(0));
404dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GE(io_watcher_->ping_sequence_number_, static_cast<uint64>(0));
405dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GT(io_watcher_->success_response_, static_cast<uint64>(0));
406dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(io_watcher_->failed_response_, static_cast<uint64>(0));
407dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
408dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // DeActivate thread watching for shutdown.
409dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WatchDogThread::PostTask(
410dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
411dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(io_watcher_, &ThreadWatcher::DeActivateThreadWatching));
412dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
413dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WatchDogThread::PostTask(
414dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
415dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(
416dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          webkit_watcher_, &ThreadWatcher::DeActivateThreadWatching));
417dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
418dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
419dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Test watching of multiple threads with one of the threads not responding.
420dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenTEST_F(ThreadWatcherTest, MultipleThreadsNotResponding) {
421dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Simulate hanging of watched thread by making the watched thread wait for a
422dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // very long time by posting a task on watched thread that keeps it busy.
423dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  BrowserThread::PostTask(
424dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      io_thread_id,
425dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
426dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(
427dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          io_watcher_,
428dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          &CustomThreadWatcher::VeryLongMethod,
429dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          kUnresponsiveTime * 10));
430dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
431dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Activate watching of WEBKIT thread.
432dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WatchDogThread::PostTask(
433dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
434dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(
435dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          webkit_watcher_, &ThreadWatcher::ActivateThreadWatching));
436dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
437dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Activate watching of IO thread.
438dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WatchDogThread::PostTask(
439dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
440dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(io_watcher_, &ThreadWatcher::ActivateThreadWatching));
441dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
442dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Verify WEBKIT thread is responding with ping/pong messaging.
443dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  webkit_watcher_->WaitForCheckResponse(
444dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      kUnresponsiveTime + TimeDelta::FromMinutes(1), SUCCESSFUL);
445dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GT(webkit_watcher_->success_response_, static_cast<uint64>(0));
446dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(webkit_watcher_->failed_response_, static_cast<uint64>(0));
447dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
448dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Verify IO thread is not responding for ping messages.
449dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  io_watcher_->WaitForCheckResponse(
450dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      kUnresponsiveTime + TimeDelta::FromMinutes(1), FAILED);
451dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_EQ(io_watcher_->success_response_, static_cast<uint64>(0));
452dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EXPECT_GT(io_watcher_->failed_response_, static_cast<uint64>(0));
453dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
454dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // DeActivate thread watching for shutdown.
455dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WatchDogThread::PostTask(
456dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
457dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(io_watcher_, &ThreadWatcher::DeActivateThreadWatching));
458dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  WatchDogThread::PostTask(
459dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      FROM_HERE,
460dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NewRunnableMethod(
461dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          webkit_watcher_, &ThreadWatcher::DeActivateThreadWatching));
462dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
463dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Wait for the io_watcher_'s VeryLongMethod to finish.
464dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE);
465dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
466