Index: chrome/browser/metrics/thread_watcher_unittest.cc |
=================================================================== |
--- chrome/browser/metrics/thread_watcher_unittest.cc (revision 89361) |
+++ chrome/browser/metrics/thread_watcher_unittest.cc (working copy) |
@@ -2,17 +2,21 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include <math.h> |
+ |
#include "base/basictypes.h" |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/message_loop.h" |
#include "base/message_loop_proxy.h" |
+#include "base/string_tokenizer.h" |
#include "base/synchronization/condition_variable.h" |
#include "base/synchronization/lock.h" |
#include "base/threading/platform_thread.h" |
#include "base/time.h" |
#include "build/build_config.h" |
#include "chrome/browser/metrics/thread_watcher.h" |
+#include "chrome/common/chrome_switches.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "testing/platform_test.h" |
@@ -64,7 +68,9 @@ |
const std::string thread_name, |
const TimeDelta& sleep_time, |
const TimeDelta& unresponsive_time) |
- : ThreadWatcher(thread_id, thread_name, sleep_time, unresponsive_time), |
+ : ThreadWatcher(thread_id, thread_name, sleep_time, unresponsive_time, |
+ ThreadWatcherList::kUnresponsiveCount, true, |
+ ThreadWatcherList::kLiveThreadsThreshold), |
state_changed_(&custom_lock_), |
thread_watcher_state_(INITIALIZED), |
wait_state_(UNINITIALIZED), |
@@ -233,10 +239,16 @@ |
static const std::string io_thread_name; |
static const BrowserThread::ID webkit_thread_id; |
static const std::string webkit_thread_name; |
+ static const std::string crash_on_hang_seconds; |
+ static const std::string crash_on_hang_threads; |
+ static const std::string crash_on_live; |
CustomThreadWatcher* io_watcher_; |
CustomThreadWatcher* webkit_watcher_; |
+ ThreadWatcherList* thread_watcher_list_; |
- ThreadWatcherTest() { |
+ ThreadWatcherTest() |
+ : setup_complete_(&lock_), |
+ initialized_(false) { |
webkit_thread_.reset(new BrowserThread(BrowserThread::WEBKIT)); |
io_thread_.reset(new BrowserThread(BrowserThread::IO)); |
watchdog_thread_.reset(new WatchDogThread()); |
@@ -244,35 +256,69 @@ |
io_thread_->Start(); |
watchdog_thread_->Start(); |
+ WatchDogThread::PostTask( |
+ FROM_HERE, |
+ NewRunnableMethod(this, &ThreadWatcherTest::SetUpObjects)); |
+ |
+ WaitForSetUp(TimeDelta::FromMinutes(1)); |
+ } |
+ |
+ void SetUpObjects() { |
+ DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
+ |
// Setup the registry for thread watchers. |
thread_watcher_list_ = new ThreadWatcherList(); |
// Create thread watcher object for the IO thread. |
io_watcher_ = new CustomThreadWatcher(io_thread_id, io_thread_name, |
kSleepTime, kUnresponsiveTime); |
+ EXPECT_EQ(io_watcher_, thread_watcher_list_->Find(io_thread_id)); |
// Create thread watcher object for the WEBKIT thread. |
webkit_watcher_ = new CustomThreadWatcher( |
webkit_thread_id, webkit_thread_name, kSleepTime, kUnresponsiveTime); |
+ EXPECT_EQ(webkit_watcher_, thread_watcher_list_->Find(webkit_thread_id)); |
+ |
+ { |
+ base::AutoLock lock(lock_); |
+ initialized_ = true; |
+ } |
+ setup_complete_.Signal(); |
} |
+ void WaitForSetUp(TimeDelta wait_time) { |
+ DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread()); |
+ TimeTicks end_time = TimeTicks::Now() + wait_time; |
+ { |
+ base::AutoLock auto_lock(lock_); |
+ while (!initialized_ && TimeTicks::Now() < end_time) |
+ setup_complete_.TimedWait(end_time - TimeTicks::Now()); |
+ } |
+ } |
+ |
~ThreadWatcherTest() { |
- ThreadWatcherList::StopWatchingAll(); |
+ ThreadWatcherList::DeleteAll(); |
io_watcher_ = NULL; |
webkit_watcher_ = NULL; |
io_thread_.reset(); |
webkit_thread_.reset(); |
watchdog_thread_.reset(); |
- delete thread_watcher_list_; |
+ thread_watcher_list_ = NULL; |
} |
private: |
+ base::Lock lock_; |
+ base::ConditionVariable setup_complete_; |
+ bool initialized_; |
scoped_ptr<BrowserThread> webkit_thread_; |
scoped_ptr<BrowserThread> io_thread_; |
scoped_ptr<WatchDogThread> watchdog_thread_; |
- ThreadWatcherList* thread_watcher_list_; |
}; |
+// DISABLE_RUNNABLE_METHOD_REFCOUNT is a convenience macro for disabling |
+// refcounting of ThreadWatcherTest classes. |
+DISABLE_RUNNABLE_METHOD_REFCOUNT(ThreadWatcherTest); |
+ |
// Define static constants. |
const TimeDelta ThreadWatcherTest::kSleepTime = |
TimeDelta::FromMilliseconds(50); |
@@ -283,13 +329,52 @@ |
const BrowserThread::ID ThreadWatcherTest::webkit_thread_id = |
BrowserThread::WEBKIT; |
const std::string ThreadWatcherTest::webkit_thread_name = "WEBKIT"; |
+const std::string ThreadWatcherTest::crash_on_hang_seconds = "24"; |
+const std::string ThreadWatcherTest::crash_on_hang_threads = "IO,UI"; |
+const std::string ThreadWatcherTest::crash_on_live = "3"; |
+TEST_F(ThreadWatcherTest, CommandLineArgs) { |
+ // Setup command_line arguments. |
+ CommandLine command_line(CommandLine::NO_PROGRAM); |
+ command_line.AppendSwitchASCII(switches::kCrashOnHangSeconds, |
+ crash_on_hang_seconds); |
+ command_line.AppendSwitchASCII(switches::kCrashOnHangThreads, |
+ crash_on_hang_threads); |
+ command_line.AppendSwitchASCII(switches::kCrashOnLive, |
+ crash_on_live); |
+ |
+ // Parse command_line arguments. |
+ uint32 unresponsive_threshold; |
+ std::set<std::string> crash_on_hang_thread_names; |
+ uint32 live_threads_threshold; |
+ ThreadWatcherList::ParseCommandLine(command_line, |
+ &unresponsive_threshold, |
+ &crash_on_hang_thread_names, |
+ &live_threads_threshold); |
+ |
+ // Verify the data. |
+ uint32 crash_on_unresponsive_seconds = |
+ ThreadWatcherList::kUnresponsiveSeconds * unresponsive_threshold; |
+ EXPECT_EQ(static_cast<int>(crash_on_unresponsive_seconds), |
+ atoi(crash_on_hang_seconds.c_str())); |
+ |
+ // Check ThreadWatcherTestList has the right crash_on_hang_threads. |
+ StringTokenizer tokens(crash_on_hang_threads, ","); |
+ while (tokens.GetNext()) { |
+ std::string thread_name = tokens.token(); |
+ std::set<std::string>::iterator it = |
+ crash_on_hang_thread_names.find(thread_name); |
+ bool crash_on_hang = (it != crash_on_hang_thread_names.end()); |
+ EXPECT_TRUE(crash_on_hang); |
+ } |
+ |
+ EXPECT_EQ(static_cast<int>(live_threads_threshold), |
+ atoi(crash_on_live.c_str())); |
+} |
+ |
// Test registration. When thread_watcher_list_ goes out of scope after |
// TearDown, all thread watcher objects will be deleted. |
TEST_F(ThreadWatcherTest, Registration) { |
- EXPECT_EQ(io_watcher_, ThreadWatcherList::Find(io_thread_id)); |
- EXPECT_EQ(webkit_watcher_, ThreadWatcherList::Find(webkit_thread_id)); |
- |
// Check ThreadWatcher object has all correct parameters. |
EXPECT_EQ(io_thread_id, io_watcher_->thread_id()); |
EXPECT_EQ(io_thread_name, io_watcher_->thread_name()); |