Make castv2 performance test work.
[chromium-blink-merge.git] / chrome / browser / metrics / thread_watcher_unittest.cc
bloba53cd490d79b5e5bf46b583e5a9a9169a76bd964
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <math.h>
7 #include "base/basictypes.h"
8 #include "base/bind.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/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"
28 using base::TimeDelta;
29 using base::TimeTicks;
30 using content::BrowserThread;
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.
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.
47 enum CheckResponseState {
48 UNKNOWN,
49 SUCCESSFUL, // CheckResponse was successful.
50 FAILED, // CheckResponse has failed.
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_;
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) {
92 State UpdateState(State new_state) {
93 State old_state;
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();
106 state_changed_.Broadcast();
107 return old_state;
110 WaitState UpdateWaitState(WaitState new_state) {
111 WaitState old_state;
113 base::AutoLock auto_lock(custom_lock_);
114 old_state = wait_state_;
115 wait_state_ = new_state;
117 state_changed_.Broadcast();
118 return old_state;
121 void ActivateThreadWatching() override {
122 State old_state = UpdateState(ACTIVATED);
123 EXPECT_EQ(old_state, INITIALIZED);
124 ThreadWatcher::ActivateThreadWatching();
127 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();
134 void PostPingMessage() override {
135 State old_state = UpdateState(SENT_PING);
136 EXPECT_TRUE(old_state == ACTIVATED || old_state == RECEIVED_PONG);
137 ThreadWatcher::PostPingMessage();
140 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);
146 void OnCheckResponsiveness(uint64 ping_sequence_number) override {
147 ThreadWatcher::OnCheckResponsiveness(ping_sequence_number);
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;
160 // Broadcast to indicate we have checked responsiveness of the thread that
161 // is watched.
162 state_changed_.Broadcast();
165 void WaitForWaitStateChange(TimeDelta wait_time, WaitState expected_state) {
166 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
167 TimeTicks end_time = TimeTicks::Now() + wait_time;
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());
175 void VeryLongMethod(TimeDelta wait_time) {
176 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
177 WaitForWaitStateChange(wait_time, STOPPED_WAITING);
178 UpdateWaitState(ALL_DONE);
181 State WaitForStateChange(const TimeDelta& wait_time, State expected_state) {
182 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
183 UpdateWaitState(STARTED_WAITING);
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;
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);
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;
204 UpdateWaitState(STOPPED_WAITING);
205 return exit_state;
208 CheckResponseState WaitForCheckResponse(const TimeDelta& wait_time,
209 CheckResponseState expected_state) {
210 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
211 UpdateWaitState(STARTED_WAITING);
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;
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);
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;
233 UpdateWaitState(STOPPED_WAITING);
234 return exit_state;
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_;
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();
264 WatchDogThread::PostTask(
265 FROM_HERE,
266 base::Bind(&ThreadWatcherTest::SetUpObjects, base::Unretained(this)));
268 WaitForSetUp(TimeDelta::FromMinutes(1));
271 void SetUpObjects() {
272 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
274 // Setup the registry for thread watchers.
275 thread_watcher_list_ = new ThreadWatcherList();
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));
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));
288 base::AutoLock lock(lock_);
289 initialized_ = true;
291 setup_complete_.Signal();
294 void WaitForSetUp(TimeDelta wait_time) {
295 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
296 TimeTicks end_time = TimeTicks::Now() + wait_time;
298 base::AutoLock auto_lock(lock_);
299 while (!initialized_ && TimeTicks::Now() < end_time)
300 setup_complete_.TimedWait(end_time - TimeTicks::Now());
304 ~ThreadWatcherTest() override {
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;
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_;
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";
338 TEST_F(ThreadWatcherTest, ThreadNamesOnlyArgs) {
339 // Setup command_line arguments.
340 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
341 command_line.AppendSwitchASCII(switches::kCrashOnHangThreads,
342 crash_on_hang_thread_names);
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);
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];
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);
368 TEST_F(ThreadWatcherTest, ThreadNamesAndLiveThresholdArgs) {
369 // Setup command_line arguments.
370 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
371 command_line.AppendSwitchASCII(switches::kCrashOnHangThreads,
372 thread_names_and_live_threshold);
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);
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];
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);
398 TEST_F(ThreadWatcherTest, CrashOnHangThreadsAllArgs) {
399 // Setup command_line arguments.
400 base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
401 command_line.AppendSwitchASCII(switches::kCrashOnHangThreads,
402 crash_on_hang_thread_data);
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);
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];
419 ThreadWatcherList::CrashOnHangThreadMap::iterator it =
420 crash_on_hang_threads.find(thread_name);
422 bool crash_on_hang = (it != crash_on_hang_threads.end());
423 EXPECT_TRUE(crash_on_hang);
425 uint32 crash_live_threads_threshold = it->second.live_threads_threshold;
426 EXPECT_EQ(5u, crash_live_threads_threshold);
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);
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());
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());
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_)));
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));
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));
484 // DeActivate thread watching for shutdown.
485 WatchDogThread::PostTask(
486 FROM_HERE,
487 base::Bind(&ThreadWatcher::DeActivateThreadWatching,
488 base::Unretained(io_watcher_)));
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));
507 // Activate thread watching.
508 WatchDogThread::PostTask(
509 FROM_HERE,
510 base::Bind(&ThreadWatcher::ActivateThreadWatching,
511 base::Unretained(io_watcher_)));
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));
521 // DeActivate thread watching for shutdown.
522 WatchDogThread::PostTask(
523 FROM_HERE,
524 base::Bind(&ThreadWatcher::DeActivateThreadWatching,
525 base::Unretained(io_watcher_)));
527 // Wait for the io_watcher_'s VeryLongMethod to finish.
528 io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE);
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_)));
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_)));
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));
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));
567 // DeActivate thread watching for shutdown.
568 WatchDogThread::PostTask(
569 FROM_HERE,
570 base::Bind(&ThreadWatcher::DeActivateThreadWatching,
571 base::Unretained(io_watcher_)));
573 WatchDogThread::PostTask(
574 FROM_HERE,
575 base::Bind(&ThreadWatcher::DeActivateThreadWatching,
576 base::Unretained(db_watcher_)));
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));
592 // Activate watching of DB thread.
593 WatchDogThread::PostTask(
594 FROM_HERE,
595 base::Bind(&ThreadWatcher::ActivateThreadWatching,
596 base::Unretained(db_watcher_)));
598 // Activate watching of IO thread.
599 WatchDogThread::PostTask(
600 FROM_HERE,
601 base::Bind(&ThreadWatcher::ActivateThreadWatching,
602 base::Unretained(io_watcher_)));
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));
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));
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_)));
630 // Wait for the io_watcher_'s VeryLongMethod to finish.
631 io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE);
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) {
643 void ReadStateOnWatchDogThread() {
644 CHECK(WatchDogThread::CurrentlyOnWatchDogThread());
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;
652 done_.Signal();
655 void CheckState(bool has_thread_watcher_list,
656 bool stopped,
657 const char* const msg) {
658 CHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
660 base::AutoLock auto_lock(lock_);
661 state_available_ = false;
664 WatchDogThread::PostTask(
665 FROM_HERE,
666 base::Bind(&ThreadWatcherListTest::ReadStateOnWatchDogThread,
667 base::Unretained(this)));
669 base::AutoLock auto_lock(lock_);
670 while (!state_available_)
671 done_.Wait();
673 EXPECT_EQ(has_thread_watcher_list, has_thread_watcher_list_) << msg;
674 EXPECT_EQ(stopped, stopped_) << msg;
678 base::Lock lock_;
679 base::ConditionVariable done_;
681 bool state_available_;
682 bool has_thread_watcher_list_;
683 bool stopped_;
686 TEST_F(ThreadWatcherListTest, Restart) {
687 ThreadWatcherList::g_initialize_delay_seconds = 1;
689 base::MessageLoopForUI message_loop_for_ui;
690 content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop_for_ui);
692 scoped_ptr<WatchDogThread> watchdog_thread_(new WatchDogThread());
693 watchdog_thread_->Start();
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(*base::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();
709 CheckState(false /* has_thread_watcher_list */,
710 true /* stopped */,
711 "Start / Stopped");
713 // Proceed with just |StartWatchingAll| and ensure it'll be started.
714 ThreadWatcherList::StartWatchingAll(*base::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();
722 CheckState(true /* has_thread_watcher_list */,
723 false /* stopped */,
724 "Started");
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();
735 CheckState(false /* has_thread_watcher_list */,
736 true /* stopped */,
737 "Stopped");