OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 <math.h> | 5 #include <math.h> |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 class ThreadWatcherTest : public ::testing::Test { | 235 class ThreadWatcherTest : public ::testing::Test { |
236 public: | 236 public: |
237 static const TimeDelta kSleepTime; | 237 static const TimeDelta kSleepTime; |
238 static const TimeDelta kUnresponsiveTime; | 238 static const TimeDelta kUnresponsiveTime; |
239 static const BrowserThread::ID io_thread_id; | 239 static const BrowserThread::ID io_thread_id; |
240 static const std::string io_thread_name; | 240 static const std::string io_thread_name; |
241 static const BrowserThread::ID webkit_thread_id; | 241 static const BrowserThread::ID webkit_thread_id; |
242 static const std::string webkit_thread_name; | 242 static const std::string webkit_thread_name; |
243 static const std::string crash_on_hang_seconds; | 243 static const std::string crash_on_hang_seconds; |
244 static const std::string crash_on_hang_thread_names; | 244 static const std::string crash_on_hang_thread_names; |
| 245 static const std::string thread_names_and_live_threshold; |
| 246 static const std::string crash_on_hang_thread_data; |
245 CustomThreadWatcher* io_watcher_; | 247 CustomThreadWatcher* io_watcher_; |
246 CustomThreadWatcher* webkit_watcher_; | 248 CustomThreadWatcher* webkit_watcher_; |
247 ThreadWatcherList* thread_watcher_list_; | 249 ThreadWatcherList* thread_watcher_list_; |
248 | 250 |
249 ThreadWatcherTest() | 251 ThreadWatcherTest() |
250 : setup_complete_(&lock_), | 252 : setup_complete_(&lock_), |
251 initialized_(false) { | 253 initialized_(false) { |
252 webkit_thread_.reset(new content::TestBrowserThread( | 254 webkit_thread_.reset(new content::TestBrowserThread( |
253 BrowserThread::WEBKIT_DEPRECATED)); | 255 BrowserThread::WEBKIT_DEPRECATED)); |
254 io_thread_.reset(new content::TestBrowserThread(BrowserThread::IO)); | 256 io_thread_.reset(new content::TestBrowserThread(BrowserThread::IO)); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 // Define static constants. | 321 // Define static constants. |
320 const TimeDelta ThreadWatcherTest::kSleepTime = | 322 const TimeDelta ThreadWatcherTest::kSleepTime = |
321 TimeDelta::FromMilliseconds(50); | 323 TimeDelta::FromMilliseconds(50); |
322 const TimeDelta ThreadWatcherTest::kUnresponsiveTime = | 324 const TimeDelta ThreadWatcherTest::kUnresponsiveTime = |
323 TimeDelta::FromMilliseconds(500); | 325 TimeDelta::FromMilliseconds(500); |
324 const BrowserThread::ID ThreadWatcherTest::io_thread_id = BrowserThread::IO; | 326 const BrowserThread::ID ThreadWatcherTest::io_thread_id = BrowserThread::IO; |
325 const std::string ThreadWatcherTest::io_thread_name = "IO"; | 327 const std::string ThreadWatcherTest::io_thread_name = "IO"; |
326 const BrowserThread::ID ThreadWatcherTest::webkit_thread_id = | 328 const BrowserThread::ID ThreadWatcherTest::webkit_thread_id = |
327 BrowserThread::WEBKIT_DEPRECATED; | 329 BrowserThread::WEBKIT_DEPRECATED; |
328 const std::string ThreadWatcherTest::webkit_thread_name = "WEBKIT"; | 330 const std::string ThreadWatcherTest::webkit_thread_name = "WEBKIT"; |
329 const std::string ThreadWatcherTest::crash_on_hang_seconds = "24"; | 331 const std::string ThreadWatcherTest::crash_on_hang_thread_names = "UI,IO"; |
330 const std::string ThreadWatcherTest::crash_on_hang_thread_names = "IO:3,UI:3"; | 332 const std::string ThreadWatcherTest::thread_names_and_live_threshold = |
| 333 "UI:4,IO:4"; |
| 334 const std::string ThreadWatcherTest::crash_on_hang_thread_data = |
| 335 "UI:5:12,IO:5:12,FILE:5:12"; |
331 | 336 |
332 TEST_F(ThreadWatcherTest, CommandLineArgs) { | 337 TEST_F(ThreadWatcherTest, ThreadNamesOnlyArgs) { |
333 // Setup command_line arguments. | 338 // Setup command_line arguments. |
334 CommandLine command_line(CommandLine::NO_PROGRAM); | 339 CommandLine command_line(CommandLine::NO_PROGRAM); |
335 command_line.AppendSwitchASCII(switches::kCrashOnHangSeconds, | |
336 crash_on_hang_seconds); | |
337 command_line.AppendSwitchASCII(switches::kCrashOnHangThreads, | 340 command_line.AppendSwitchASCII(switches::kCrashOnHangThreads, |
338 crash_on_hang_thread_names); | 341 crash_on_hang_thread_names); |
339 | 342 |
340 // Parse command_line arguments. | 343 // Parse command_line arguments. |
| 344 ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads; |
341 uint32 unresponsive_threshold; | 345 uint32 unresponsive_threshold; |
342 ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads; | |
343 ThreadWatcherList::ParseCommandLine(command_line, | 346 ThreadWatcherList::ParseCommandLine(command_line, |
344 &unresponsive_threshold, | 347 &unresponsive_threshold, |
345 &crash_on_hang_threads); | 348 &crash_on_hang_threads); |
346 | 349 |
347 // Verify the data. | 350 // Verify the data. |
348 uint32 crash_on_unresponsive_seconds = | |
349 ThreadWatcherList::kUnresponsiveSeconds * unresponsive_threshold; | |
350 EXPECT_EQ(static_cast<int>(crash_on_unresponsive_seconds), | |
351 atoi(crash_on_hang_seconds.c_str())); | |
352 | |
353 // Check ThreadWatcherTestList has the right crash_on_hang_thread_names. | |
354 base::StringTokenizer tokens(crash_on_hang_thread_names, ","); | 351 base::StringTokenizer tokens(crash_on_hang_thread_names, ","); |
355 std::vector<std::string> values; | 352 std::vector<std::string> values; |
356 while (tokens.GetNext()) { | 353 while (tokens.GetNext()) { |
357 const std::string& token = tokens.token(); | 354 const std::string& token = tokens.token(); |
358 base::SplitString(token, ':', &values); | 355 base::SplitString(token, ':', &values); |
359 if (values.size() != 2) | |
360 continue; | |
361 std::string thread_name = values[0]; | 356 std::string thread_name = values[0]; |
362 uint32 live_threads_threshold; | 357 |
363 if (!base::StringToUint(values[1], &live_threads_threshold)) | |
364 continue; | |
365 ThreadWatcherList::CrashOnHangThreadMap::iterator it = | 358 ThreadWatcherList::CrashOnHangThreadMap::iterator it = |
366 crash_on_hang_threads.find(thread_name); | 359 crash_on_hang_threads.find(thread_name); |
367 bool crash_on_hang = (it != crash_on_hang_threads.end()); | 360 bool crash_on_hang = (it != crash_on_hang_threads.end()); |
368 EXPECT_TRUE(crash_on_hang); | 361 EXPECT_TRUE(crash_on_hang); |
369 EXPECT_EQ(it->second, live_threads_threshold); | 362 EXPECT_LT(0u, it->second.live_threads_threshold); |
| 363 EXPECT_LT(0u, it->second.unresponsive_threshold); |
370 } | 364 } |
371 } | 365 } |
372 | 366 |
| 367 TEST_F(ThreadWatcherTest, ThreadNamesAndLiveThresholdArgs) { |
| 368 // Setup command_line arguments. |
| 369 CommandLine command_line(CommandLine::NO_PROGRAM); |
| 370 command_line.AppendSwitchASCII(switches::kCrashOnHangThreads, |
| 371 thread_names_and_live_threshold); |
| 372 |
| 373 // Parse command_line arguments. |
| 374 ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads; |
| 375 uint32 unresponsive_threshold; |
| 376 ThreadWatcherList::ParseCommandLine(command_line, |
| 377 &unresponsive_threshold, |
| 378 &crash_on_hang_threads); |
| 379 |
| 380 // Verify the data. |
| 381 base::StringTokenizer tokens(thread_names_and_live_threshold, ","); |
| 382 std::vector<std::string> values; |
| 383 while (tokens.GetNext()) { |
| 384 const std::string& token = tokens.token(); |
| 385 base::SplitString(token, ':', &values); |
| 386 std::string thread_name = values[0]; |
| 387 |
| 388 ThreadWatcherList::CrashOnHangThreadMap::iterator it = |
| 389 crash_on_hang_threads.find(thread_name); |
| 390 bool crash_on_hang = (it != crash_on_hang_threads.end()); |
| 391 EXPECT_TRUE(crash_on_hang); |
| 392 EXPECT_EQ(4u, it->second.live_threads_threshold); |
| 393 EXPECT_LT(0u, it->second.unresponsive_threshold); |
| 394 } |
| 395 } |
| 396 |
| 397 TEST_F(ThreadWatcherTest, CrashOnHangThreadsAllArgs) { |
| 398 // Setup command_line arguments. |
| 399 CommandLine command_line(CommandLine::NO_PROGRAM); |
| 400 command_line.AppendSwitchASCII(switches::kCrashOnHangThreads, |
| 401 crash_on_hang_thread_data); |
| 402 |
| 403 // Parse command_line arguments. |
| 404 ThreadWatcherList::CrashOnHangThreadMap crash_on_hang_threads; |
| 405 uint32 unresponsive_threshold; |
| 406 ThreadWatcherList::ParseCommandLine(command_line, |
| 407 &unresponsive_threshold, |
| 408 &crash_on_hang_threads); |
| 409 |
| 410 // Verify the data. |
| 411 base::StringTokenizer tokens(crash_on_hang_thread_data, ","); |
| 412 std::vector<std::string> values; |
| 413 while (tokens.GetNext()) { |
| 414 const std::string& token = tokens.token(); |
| 415 base::SplitString(token, ':', &values); |
| 416 std::string thread_name = values[0]; |
| 417 |
| 418 ThreadWatcherList::CrashOnHangThreadMap::iterator it = |
| 419 crash_on_hang_threads.find(thread_name); |
| 420 |
| 421 bool crash_on_hang = (it != crash_on_hang_threads.end()); |
| 422 EXPECT_TRUE(crash_on_hang); |
| 423 |
| 424 uint32 crash_live_threads_threshold = it->second.live_threads_threshold; |
| 425 EXPECT_EQ(5u, crash_live_threads_threshold); |
| 426 |
| 427 uint32 crash_unresponsive_threshold = it->second.unresponsive_threshold; |
| 428 uint32 crash_on_unresponsive_seconds = |
| 429 ThreadWatcherList::kUnresponsiveSeconds * crash_unresponsive_threshold; |
| 430 EXPECT_EQ(12u, crash_on_unresponsive_seconds); |
| 431 } |
| 432 } |
| 433 |
373 // Test registration. When thread_watcher_list_ goes out of scope after | 434 // Test registration. When thread_watcher_list_ goes out of scope after |
374 // TearDown, all thread watcher objects will be deleted. | 435 // TearDown, all thread watcher objects will be deleted. |
375 TEST_F(ThreadWatcherTest, Registration) { | 436 TEST_F(ThreadWatcherTest, Registration) { |
376 // Check ThreadWatcher object has all correct parameters. | 437 // Check ThreadWatcher object has all correct parameters. |
377 EXPECT_EQ(io_thread_id, io_watcher_->thread_id()); | 438 EXPECT_EQ(io_thread_id, io_watcher_->thread_id()); |
378 EXPECT_EQ(io_thread_name, io_watcher_->thread_name()); | 439 EXPECT_EQ(io_thread_name, io_watcher_->thread_name()); |
379 EXPECT_EQ(kSleepTime, io_watcher_->sleep_time()); | 440 EXPECT_EQ(kSleepTime, io_watcher_->sleep_time()); |
380 EXPECT_EQ(kUnresponsiveTime, io_watcher_->unresponsive_time()); | 441 EXPECT_EQ(kUnresponsiveTime, io_watcher_->unresponsive_time()); |
381 EXPECT_FALSE(io_watcher_->active()); | 442 EXPECT_FALSE(io_watcher_->active()); |
382 | 443 |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 base::Bind(&ThreadWatcher::DeActivateThreadWatching, | 610 base::Bind(&ThreadWatcher::DeActivateThreadWatching, |
550 base::Unretained(io_watcher_))); | 611 base::Unretained(io_watcher_))); |
551 WatchDogThread::PostTask( | 612 WatchDogThread::PostTask( |
552 FROM_HERE, | 613 FROM_HERE, |
553 base::Bind(&ThreadWatcher::DeActivateThreadWatching, | 614 base::Bind(&ThreadWatcher::DeActivateThreadWatching, |
554 base::Unretained(webkit_watcher_))); | 615 base::Unretained(webkit_watcher_))); |
555 | 616 |
556 // Wait for the io_watcher_'s VeryLongMethod to finish. | 617 // Wait for the io_watcher_'s VeryLongMethod to finish. |
557 io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE); | 618 io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE); |
558 } | 619 } |
OLD | NEW |