OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/basictypes.h" | 5 #include "base/basictypes.h" |
6 #include "base/logging.h" | 6 #include "base/logging.h" |
7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/message_loop_proxy.h" | 9 #include "base/message_loop_proxy.h" |
| 10 #include "base/string_tokenizer.h" |
10 #include "base/synchronization/condition_variable.h" | 11 #include "base/synchronization/condition_variable.h" |
11 #include "base/synchronization/lock.h" | 12 #include "base/synchronization/lock.h" |
12 #include "base/threading/platform_thread.h" | 13 #include "base/threading/platform_thread.h" |
13 #include "base/time.h" | 14 #include "base/time.h" |
14 #include "build/build_config.h" | 15 #include "build/build_config.h" |
15 #include "chrome/browser/metrics/thread_watcher.h" | 16 #include "chrome/browser/metrics/thread_watcher.h" |
| 17 #include "chrome/common/chrome_switches.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
17 #include "testing/platform_test.h" | 19 #include "testing/platform_test.h" |
18 | 20 |
19 using base::TimeDelta; | 21 using base::TimeDelta; |
20 using base::TimeTicks; | 22 using base::TimeTicks; |
21 | 23 |
22 enum State { | 24 enum State { |
23 INITIALIZED, // Created ThreadWatch object. | 25 INITIALIZED, // Created ThreadWatch object. |
24 ACTIVATED, // Thread watching activated. | 26 ACTIVATED, // Thread watching activated. |
25 SENT_PING, // Sent ping message to watched thread. | 27 SENT_PING, // Sent ping message to watched thread. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 uint64 pong_received_; | 59 uint64 pong_received_; |
58 uint64 success_response_; | 60 uint64 success_response_; |
59 uint64 failed_response_; | 61 uint64 failed_response_; |
60 base::TimeTicks saved_ping_time_; | 62 base::TimeTicks saved_ping_time_; |
61 uint64 saved_ping_sequence_number_; | 63 uint64 saved_ping_sequence_number_; |
62 | 64 |
63 CustomThreadWatcher(const BrowserThread::ID thread_id, | 65 CustomThreadWatcher(const BrowserThread::ID thread_id, |
64 const std::string thread_name, | 66 const std::string thread_name, |
65 const TimeDelta& sleep_time, | 67 const TimeDelta& sleep_time, |
66 const TimeDelta& unresponsive_time) | 68 const TimeDelta& unresponsive_time) |
67 : ThreadWatcher(thread_id, thread_name, sleep_time, unresponsive_time), | 69 : ThreadWatcher(thread_id, thread_name, sleep_time, unresponsive_time, |
| 70 ThreadWatcherList::kUnresponsiveCount, false), |
68 state_changed_(&custom_lock_), | 71 state_changed_(&custom_lock_), |
69 thread_watcher_state_(INITIALIZED), | 72 thread_watcher_state_(INITIALIZED), |
70 wait_state_(UNINITIALIZED), | 73 wait_state_(UNINITIALIZED), |
71 check_response_state_(UNKNOWN), | 74 check_response_state_(UNKNOWN), |
72 ping_sent_(0), | 75 ping_sent_(0), |
73 pong_received_(0), | 76 pong_received_(0), |
74 success_response_(0), | 77 success_response_(0), |
75 failed_response_(0), | 78 failed_response_(0), |
76 saved_ping_time_(base::TimeTicks::Now()), | 79 saved_ping_time_(base::TimeTicks::Now()), |
77 saved_ping_sequence_number_(0) { | 80 saved_ping_sequence_number_(0) { |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 DISABLE_RUNNABLE_METHOD_REFCOUNT(CustomThreadWatcher); | 229 DISABLE_RUNNABLE_METHOD_REFCOUNT(CustomThreadWatcher); |
227 | 230 |
228 class ThreadWatcherTest : public ::testing::Test { | 231 class ThreadWatcherTest : public ::testing::Test { |
229 public: | 232 public: |
230 static const TimeDelta kSleepTime; | 233 static const TimeDelta kSleepTime; |
231 static const TimeDelta kUnresponsiveTime; | 234 static const TimeDelta kUnresponsiveTime; |
232 static const BrowserThread::ID io_thread_id; | 235 static const BrowserThread::ID io_thread_id; |
233 static const std::string io_thread_name; | 236 static const std::string io_thread_name; |
234 static const BrowserThread::ID webkit_thread_id; | 237 static const BrowserThread::ID webkit_thread_id; |
235 static const std::string webkit_thread_name; | 238 static const std::string webkit_thread_name; |
| 239 static const std::string crash_on_hang_seconds; |
| 240 static const std::string crash_on_hang_threads; |
| 241 |
236 CustomThreadWatcher* io_watcher_; | 242 CustomThreadWatcher* io_watcher_; |
237 CustomThreadWatcher* webkit_watcher_; | 243 CustomThreadWatcher* webkit_watcher_; |
| 244 ThreadWatcherList* thread_watcher_list_; |
238 | 245 |
239 ThreadWatcherTest() { | 246 ThreadWatcherTest() { |
240 webkit_thread_.reset(new BrowserThread(BrowserThread::WEBKIT)); | 247 webkit_thread_.reset(new BrowserThread(BrowserThread::WEBKIT)); |
241 io_thread_.reset(new BrowserThread(BrowserThread::IO)); | 248 io_thread_.reset(new BrowserThread(BrowserThread::IO)); |
242 watchdog_thread_.reset(new WatchDogThread()); | 249 watchdog_thread_.reset(new WatchDogThread()); |
243 webkit_thread_->Start(); | 250 webkit_thread_->Start(); |
244 io_thread_->Start(); | 251 io_thread_->Start(); |
245 watchdog_thread_->Start(); | 252 watchdog_thread_->Start(); |
246 | 253 |
| 254 CommandLine command_line(CommandLine::NO_PROGRAM); |
| 255 command_line.AppendSwitchASCII(switches::kCrashOnHangSeconds, |
| 256 crash_on_hang_seconds); |
| 257 command_line.AppendSwitchASCII(switches::kCrashOnHangThreads, |
| 258 crash_on_hang_threads); |
| 259 |
247 // Setup the registry for thread watchers. | 260 // Setup the registry for thread watchers. |
248 thread_watcher_list_ = new ThreadWatcherList(); | 261 thread_watcher_list_ = new ThreadWatcherList(command_line); |
249 | 262 |
250 // Create thread watcher object for the IO thread. | 263 // Create thread watcher object for the IO thread. |
251 io_watcher_ = new CustomThreadWatcher(io_thread_id, io_thread_name, | 264 io_watcher_ = new CustomThreadWatcher(io_thread_id, io_thread_name, |
252 kSleepTime, kUnresponsiveTime); | 265 kSleepTime, kUnresponsiveTime); |
253 | 266 |
254 // Create thread watcher object for the WEBKIT thread. | 267 // Create thread watcher object for the WEBKIT thread. |
255 webkit_watcher_ = new CustomThreadWatcher( | 268 webkit_watcher_ = new CustomThreadWatcher( |
256 webkit_thread_id, webkit_thread_name, kSleepTime, kUnresponsiveTime); | 269 webkit_thread_id, webkit_thread_name, kSleepTime, kUnresponsiveTime); |
257 } | 270 } |
258 | 271 |
259 ~ThreadWatcherTest() { | 272 ~ThreadWatcherTest() { |
260 ThreadWatcherList::StopWatchingAll(); | 273 ThreadWatcherList::StopWatchingAll(); |
261 io_watcher_ = NULL; | 274 io_watcher_ = NULL; |
262 webkit_watcher_ = NULL; | 275 webkit_watcher_ = NULL; |
263 io_thread_.reset(); | 276 io_thread_.reset(); |
264 webkit_thread_.reset(); | 277 webkit_thread_.reset(); |
265 watchdog_thread_.reset(); | 278 watchdog_thread_.reset(); |
266 delete thread_watcher_list_; | 279 delete thread_watcher_list_; |
267 } | 280 } |
268 | 281 |
269 private: | 282 private: |
270 scoped_ptr<BrowserThread> webkit_thread_; | 283 scoped_ptr<BrowserThread> webkit_thread_; |
271 scoped_ptr<BrowserThread> io_thread_; | 284 scoped_ptr<BrowserThread> io_thread_; |
272 scoped_ptr<WatchDogThread> watchdog_thread_; | 285 scoped_ptr<WatchDogThread> watchdog_thread_; |
273 ThreadWatcherList* thread_watcher_list_; | |
274 }; | 286 }; |
275 | 287 |
276 // Define static constants. | 288 // Define static constants. |
277 const TimeDelta ThreadWatcherTest::kSleepTime = | 289 const TimeDelta ThreadWatcherTest::kSleepTime = |
278 TimeDelta::FromMilliseconds(50); | 290 TimeDelta::FromMilliseconds(50); |
279 const TimeDelta ThreadWatcherTest::kUnresponsiveTime = | 291 const TimeDelta ThreadWatcherTest::kUnresponsiveTime = |
280 TimeDelta::FromMilliseconds(500); | 292 TimeDelta::FromMilliseconds(500); |
281 const BrowserThread::ID ThreadWatcherTest::io_thread_id = BrowserThread::IO; | 293 const BrowserThread::ID ThreadWatcherTest::io_thread_id = BrowserThread::IO; |
282 const std::string ThreadWatcherTest::io_thread_name = "IO"; | 294 const std::string ThreadWatcherTest::io_thread_name = "IO"; |
283 const BrowserThread::ID ThreadWatcherTest::webkit_thread_id = | 295 const BrowserThread::ID ThreadWatcherTest::webkit_thread_id = |
284 BrowserThread::WEBKIT; | 296 BrowserThread::WEBKIT; |
285 const std::string ThreadWatcherTest::webkit_thread_name = "WEBKIT"; | 297 const std::string ThreadWatcherTest::webkit_thread_name = "WEBKIT"; |
| 298 const std::string ThreadWatcherTest::crash_on_hang_seconds = "24"; |
| 299 const std::string ThreadWatcherTest::crash_on_hang_threads = "IO,UI"; |
| 300 |
| 301 TEST_F(ThreadWatcherTest, CommandLineArgs) { |
| 302 // Check ThreadWatcherTestList has the right crash_on_hang_seconds. |
| 303 uint32 crash_on_unresponsive_count = |
| 304 thread_watcher_list_->CrashOnUnresponsiveCount(); |
| 305 uint32 crash_on_unresponsive_seconds = |
| 306 ThreadWatcherList::kUnresponsiveSeconds * crash_on_unresponsive_count; |
| 307 int crash_seconds = atoi(crash_on_hang_seconds.c_str()); |
| 308 EXPECT_EQ(crash_on_unresponsive_seconds, static_cast<uint32>(crash_seconds)); |
| 309 |
| 310 // Check ThreadWatcherTestList has the right crash_on_hang_threads. |
| 311 StringTokenizer t(crash_on_hang_threads, ","); |
| 312 while (t.GetNext()) |
| 313 EXPECT_TRUE(thread_watcher_list_->CrashOnHang(t.token())); |
| 314 } |
286 | 315 |
287 // Test registration. When thread_watcher_list_ goes out of scope after | 316 // Test registration. When thread_watcher_list_ goes out of scope after |
288 // TearDown, all thread watcher objects will be deleted. | 317 // TearDown, all thread watcher objects will be deleted. |
289 TEST_F(ThreadWatcherTest, Registration) { | 318 TEST_F(ThreadWatcherTest, Registration) { |
290 EXPECT_EQ(io_watcher_, ThreadWatcherList::Find(io_thread_id)); | 319 EXPECT_EQ(io_watcher_, ThreadWatcherList::Find(io_thread_id)); |
291 EXPECT_EQ(webkit_watcher_, ThreadWatcherList::Find(webkit_thread_id)); | 320 EXPECT_EQ(webkit_watcher_, ThreadWatcherList::Find(webkit_thread_id)); |
292 | 321 |
293 // Check ThreadWatcher object has all correct parameters. | 322 // Check ThreadWatcher object has all correct parameters. |
294 EXPECT_EQ(io_thread_id, io_watcher_->thread_id()); | 323 EXPECT_EQ(io_thread_id, io_watcher_->thread_id()); |
295 EXPECT_EQ(io_thread_name, io_watcher_->thread_name()); | 324 EXPECT_EQ(io_thread_name, io_watcher_->thread_name()); |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 FROM_HERE, | 485 FROM_HERE, |
457 NewRunnableMethod(io_watcher_, &ThreadWatcher::DeActivateThreadWatching)); | 486 NewRunnableMethod(io_watcher_, &ThreadWatcher::DeActivateThreadWatching)); |
458 WatchDogThread::PostTask( | 487 WatchDogThread::PostTask( |
459 FROM_HERE, | 488 FROM_HERE, |
460 NewRunnableMethod( | 489 NewRunnableMethod( |
461 webkit_watcher_, &ThreadWatcher::DeActivateThreadWatching)); | 490 webkit_watcher_, &ThreadWatcher::DeActivateThreadWatching)); |
462 | 491 |
463 // Wait for the io_watcher_'s VeryLongMethod to finish. | 492 // Wait for the io_watcher_'s VeryLongMethod to finish. |
464 io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE); | 493 io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE); |
465 } | 494 } |
OLD | NEW |