| 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 |