Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(670)

Side by Side Diff: chrome/browser/metrics/thread_watcher_unittest.cc

Issue 7134007: Added command line switches "crash-on-hang-threads" and "crash-on-hang-seconds" (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/metrics/thread_watcher.cc ('k') | chrome/common/chrome_switches.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <math.h>
6
5 #include "base/basictypes.h" 7 #include "base/basictypes.h"
6 #include "base/logging.h" 8 #include "base/logging.h"
7 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
8 #include "base/message_loop.h" 10 #include "base/message_loop.h"
9 #include "base/message_loop_proxy.h" 11 #include "base/message_loop_proxy.h"
12 #include "base/string_tokenizer.h"
10 #include "base/synchronization/condition_variable.h" 13 #include "base/synchronization/condition_variable.h"
11 #include "base/synchronization/lock.h" 14 #include "base/synchronization/lock.h"
12 #include "base/threading/platform_thread.h" 15 #include "base/threading/platform_thread.h"
13 #include "base/time.h" 16 #include "base/time.h"
14 #include "build/build_config.h" 17 #include "build/build_config.h"
15 #include "chrome/browser/metrics/thread_watcher.h" 18 #include "chrome/browser/metrics/thread_watcher.h"
19 #include "chrome/common/chrome_switches.h"
16 #include "testing/gtest/include/gtest/gtest.h" 20 #include "testing/gtest/include/gtest/gtest.h"
17 #include "testing/platform_test.h" 21 #include "testing/platform_test.h"
18 22
19 using base::TimeDelta; 23 using base::TimeDelta;
20 using base::TimeTicks; 24 using base::TimeTicks;
21 25
22 enum State { 26 enum State {
23 INITIALIZED, // Created ThreadWatch object. 27 INITIALIZED, // Created ThreadWatch object.
24 ACTIVATED, // Thread watching activated. 28 ACTIVATED, // Thread watching activated.
25 SENT_PING, // Sent ping message to watched thread. 29 SENT_PING, // Sent ping message to watched thread.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 uint64 pong_received_; 61 uint64 pong_received_;
58 uint64 success_response_; 62 uint64 success_response_;
59 uint64 failed_response_; 63 uint64 failed_response_;
60 base::TimeTicks saved_ping_time_; 64 base::TimeTicks saved_ping_time_;
61 uint64 saved_ping_sequence_number_; 65 uint64 saved_ping_sequence_number_;
62 66
63 CustomThreadWatcher(const BrowserThread::ID thread_id, 67 CustomThreadWatcher(const BrowserThread::ID thread_id,
64 const std::string thread_name, 68 const std::string thread_name,
65 const TimeDelta& sleep_time, 69 const TimeDelta& sleep_time,
66 const TimeDelta& unresponsive_time) 70 const TimeDelta& unresponsive_time)
67 : ThreadWatcher(thread_id, thread_name, sleep_time, unresponsive_time), 71 : ThreadWatcher(thread_id, thread_name, sleep_time, unresponsive_time,
72 ThreadWatcherList::kUnresponsiveCount, true,
73 ThreadWatcherList::kLiveThreadsThreshold),
68 state_changed_(&custom_lock_), 74 state_changed_(&custom_lock_),
69 thread_watcher_state_(INITIALIZED), 75 thread_watcher_state_(INITIALIZED),
70 wait_state_(UNINITIALIZED), 76 wait_state_(UNINITIALIZED),
71 check_response_state_(UNKNOWN), 77 check_response_state_(UNKNOWN),
72 ping_sent_(0), 78 ping_sent_(0),
73 pong_received_(0), 79 pong_received_(0),
74 success_response_(0), 80 success_response_(0),
75 failed_response_(0), 81 failed_response_(0),
76 saved_ping_time_(base::TimeTicks::Now()), 82 saved_ping_time_(base::TimeTicks::Now()),
77 saved_ping_sequence_number_(0) { 83 saved_ping_sequence_number_(0) {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 DISABLE_RUNNABLE_METHOD_REFCOUNT(CustomThreadWatcher); 232 DISABLE_RUNNABLE_METHOD_REFCOUNT(CustomThreadWatcher);
227 233
228 class ThreadWatcherTest : public ::testing::Test { 234 class ThreadWatcherTest : public ::testing::Test {
229 public: 235 public:
230 static const TimeDelta kSleepTime; 236 static const TimeDelta kSleepTime;
231 static const TimeDelta kUnresponsiveTime; 237 static const TimeDelta kUnresponsiveTime;
232 static const BrowserThread::ID io_thread_id; 238 static const BrowserThread::ID io_thread_id;
233 static const std::string io_thread_name; 239 static const std::string io_thread_name;
234 static const BrowserThread::ID webkit_thread_id; 240 static const BrowserThread::ID webkit_thread_id;
235 static const std::string webkit_thread_name; 241 static const std::string webkit_thread_name;
242 static const std::string crash_on_hang_seconds;
243 static const std::string crash_on_hang_threads;
244 static const std::string crash_on_live;
236 CustomThreadWatcher* io_watcher_; 245 CustomThreadWatcher* io_watcher_;
237 CustomThreadWatcher* webkit_watcher_; 246 CustomThreadWatcher* webkit_watcher_;
247 ThreadWatcherList* thread_watcher_list_;
238 248
239 ThreadWatcherTest() { 249 ThreadWatcherTest()
250 : setup_complete_(&lock_),
251 initialized_(false) {
240 webkit_thread_.reset(new BrowserThread(BrowserThread::WEBKIT)); 252 webkit_thread_.reset(new BrowserThread(BrowserThread::WEBKIT));
241 io_thread_.reset(new BrowserThread(BrowserThread::IO)); 253 io_thread_.reset(new BrowserThread(BrowserThread::IO));
242 watchdog_thread_.reset(new WatchDogThread()); 254 watchdog_thread_.reset(new WatchDogThread());
243 webkit_thread_->Start(); 255 webkit_thread_->Start();
244 io_thread_->Start(); 256 io_thread_->Start();
245 watchdog_thread_->Start(); 257 watchdog_thread_->Start();
246 258
259 WatchDogThread::PostTask(
260 FROM_HERE,
261 NewRunnableMethod(this, &ThreadWatcherTest::SetUpObjects));
262
263 WaitForSetUp(TimeDelta::FromMinutes(1));
264 }
265
266 void SetUpObjects() {
267 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
268
247 // Setup the registry for thread watchers. 269 // Setup the registry for thread watchers.
248 thread_watcher_list_ = new ThreadWatcherList(); 270 thread_watcher_list_ = new ThreadWatcherList();
249 271
250 // Create thread watcher object for the IO thread. 272 // Create thread watcher object for the IO thread.
251 io_watcher_ = new CustomThreadWatcher(io_thread_id, io_thread_name, 273 io_watcher_ = new CustomThreadWatcher(io_thread_id, io_thread_name,
252 kSleepTime, kUnresponsiveTime); 274 kSleepTime, kUnresponsiveTime);
275 EXPECT_EQ(io_watcher_, thread_watcher_list_->Find(io_thread_id));
253 276
254 // Create thread watcher object for the WEBKIT thread. 277 // Create thread watcher object for the WEBKIT thread.
255 webkit_watcher_ = new CustomThreadWatcher( 278 webkit_watcher_ = new CustomThreadWatcher(
256 webkit_thread_id, webkit_thread_name, kSleepTime, kUnresponsiveTime); 279 webkit_thread_id, webkit_thread_name, kSleepTime, kUnresponsiveTime);
280 EXPECT_EQ(webkit_watcher_, thread_watcher_list_->Find(webkit_thread_id));
281
282 {
283 base::AutoLock lock(lock_);
284 initialized_ = true;
285 }
286 setup_complete_.Signal();
287 }
288
289 void WaitForSetUp(TimeDelta wait_time) {
290 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
291 TimeTicks end_time = TimeTicks::Now() + wait_time;
292 {
293 base::AutoLock auto_lock(lock_);
294 while (!initialized_ && TimeTicks::Now() < end_time)
295 setup_complete_.TimedWait(end_time - TimeTicks::Now());
296 }
257 } 297 }
258 298
259 ~ThreadWatcherTest() { 299 ~ThreadWatcherTest() {
260 ThreadWatcherList::StopWatchingAll(); 300 ThreadWatcherList::DeleteAll();
261 io_watcher_ = NULL; 301 io_watcher_ = NULL;
262 webkit_watcher_ = NULL; 302 webkit_watcher_ = NULL;
263 io_thread_.reset(); 303 io_thread_.reset();
264 webkit_thread_.reset(); 304 webkit_thread_.reset();
265 watchdog_thread_.reset(); 305 watchdog_thread_.reset();
266 delete thread_watcher_list_; 306 thread_watcher_list_ = NULL;
267 } 307 }
268 308
269 private: 309 private:
310 base::Lock lock_;
311 base::ConditionVariable setup_complete_;
312 bool initialized_;
270 scoped_ptr<BrowserThread> webkit_thread_; 313 scoped_ptr<BrowserThread> webkit_thread_;
271 scoped_ptr<BrowserThread> io_thread_; 314 scoped_ptr<BrowserThread> io_thread_;
272 scoped_ptr<WatchDogThread> watchdog_thread_; 315 scoped_ptr<WatchDogThread> watchdog_thread_;
273 ThreadWatcherList* thread_watcher_list_;
274 }; 316 };
275 317
318 // DISABLE_RUNNABLE_METHOD_REFCOUNT is a convenience macro for disabling
319 // refcounting of ThreadWatcherTest classes.
320 DISABLE_RUNNABLE_METHOD_REFCOUNT(ThreadWatcherTest);
321
276 // Define static constants. 322 // Define static constants.
277 const TimeDelta ThreadWatcherTest::kSleepTime = 323 const TimeDelta ThreadWatcherTest::kSleepTime =
278 TimeDelta::FromMilliseconds(50); 324 TimeDelta::FromMilliseconds(50);
279 const TimeDelta ThreadWatcherTest::kUnresponsiveTime = 325 const TimeDelta ThreadWatcherTest::kUnresponsiveTime =
280 TimeDelta::FromMilliseconds(500); 326 TimeDelta::FromMilliseconds(500);
281 const BrowserThread::ID ThreadWatcherTest::io_thread_id = BrowserThread::IO; 327 const BrowserThread::ID ThreadWatcherTest::io_thread_id = BrowserThread::IO;
282 const std::string ThreadWatcherTest::io_thread_name = "IO"; 328 const std::string ThreadWatcherTest::io_thread_name = "IO";
283 const BrowserThread::ID ThreadWatcherTest::webkit_thread_id = 329 const BrowserThread::ID ThreadWatcherTest::webkit_thread_id =
284 BrowserThread::WEBKIT; 330 BrowserThread::WEBKIT;
285 const std::string ThreadWatcherTest::webkit_thread_name = "WEBKIT"; 331 const std::string ThreadWatcherTest::webkit_thread_name = "WEBKIT";
332 const std::string ThreadWatcherTest::crash_on_hang_seconds = "24";
333 const std::string ThreadWatcherTest::crash_on_hang_threads = "IO,UI";
334 const std::string ThreadWatcherTest::crash_on_live = "3";
335
336 TEST_F(ThreadWatcherTest, CommandLineArgs) {
337 // Setup command_line arguments.
338 CommandLine command_line(CommandLine::NO_PROGRAM);
339 command_line.AppendSwitchASCII(switches::kCrashOnHangSeconds,
340 crash_on_hang_seconds);
341 command_line.AppendSwitchASCII(switches::kCrashOnHangThreads,
342 crash_on_hang_threads);
343 command_line.AppendSwitchASCII(switches::kCrashOnLive,
344 crash_on_live);
345
346 // Parse command_line arguments.
347 uint32 unresponsive_threshold;
348 std::set<std::string> crash_on_hang_thread_names;
349 uint32 live_threads_threshold;
350 ThreadWatcherList::ParseCommandLine(command_line,
351 &unresponsive_threshold,
352 &crash_on_hang_thread_names,
353 &live_threads_threshold);
354
355 // Verify the data.
356 uint32 crash_on_unresponsive_seconds =
357 ThreadWatcherList::kUnresponsiveSeconds * unresponsive_threshold;
358 EXPECT_EQ(static_cast<int>(crash_on_unresponsive_seconds),
359 atoi(crash_on_hang_seconds.c_str()));
360
361 // Check ThreadWatcherTestList has the right crash_on_hang_threads.
362 StringTokenizer tokens(crash_on_hang_threads, ",");
363 while (tokens.GetNext()) {
364 std::string thread_name = tokens.token();
365 std::set<std::string>::iterator it =
366 crash_on_hang_thread_names.find(thread_name);
367 bool crash_on_hang = (it != crash_on_hang_thread_names.end());
368 EXPECT_TRUE(crash_on_hang);
369 }
370
371 EXPECT_EQ(static_cast<int>(live_threads_threshold),
372 atoi(crash_on_live.c_str()));
373 }
286 374
287 // Test registration. When thread_watcher_list_ goes out of scope after 375 // Test registration. When thread_watcher_list_ goes out of scope after
288 // TearDown, all thread watcher objects will be deleted. 376 // TearDown, all thread watcher objects will be deleted.
289 TEST_F(ThreadWatcherTest, Registration) { 377 TEST_F(ThreadWatcherTest, Registration) {
290 EXPECT_EQ(io_watcher_, ThreadWatcherList::Find(io_thread_id));
291 EXPECT_EQ(webkit_watcher_, ThreadWatcherList::Find(webkit_thread_id));
292
293 // Check ThreadWatcher object has all correct parameters. 378 // Check ThreadWatcher object has all correct parameters.
294 EXPECT_EQ(io_thread_id, io_watcher_->thread_id()); 379 EXPECT_EQ(io_thread_id, io_watcher_->thread_id());
295 EXPECT_EQ(io_thread_name, io_watcher_->thread_name()); 380 EXPECT_EQ(io_thread_name, io_watcher_->thread_name());
296 EXPECT_EQ(kSleepTime, io_watcher_->sleep_time()); 381 EXPECT_EQ(kSleepTime, io_watcher_->sleep_time());
297 EXPECT_EQ(kUnresponsiveTime, io_watcher_->unresponsive_time()); 382 EXPECT_EQ(kUnresponsiveTime, io_watcher_->unresponsive_time());
298 EXPECT_FALSE(io_watcher_->active()); 383 EXPECT_FALSE(io_watcher_->active());
299 384
300 // Check ThreadWatcher object of watched WEBKIT thread has correct data. 385 // Check ThreadWatcher object of watched WEBKIT thread has correct data.
301 EXPECT_EQ(webkit_thread_id, webkit_watcher_->thread_id()); 386 EXPECT_EQ(webkit_thread_id, webkit_watcher_->thread_id());
302 EXPECT_EQ(webkit_thread_name, webkit_watcher_->thread_name()); 387 EXPECT_EQ(webkit_thread_name, webkit_watcher_->thread_name());
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 FROM_HERE, 541 FROM_HERE,
457 NewRunnableMethod(io_watcher_, &ThreadWatcher::DeActivateThreadWatching)); 542 NewRunnableMethod(io_watcher_, &ThreadWatcher::DeActivateThreadWatching));
458 WatchDogThread::PostTask( 543 WatchDogThread::PostTask(
459 FROM_HERE, 544 FROM_HERE,
460 NewRunnableMethod( 545 NewRunnableMethod(
461 webkit_watcher_, &ThreadWatcher::DeActivateThreadWatching)); 546 webkit_watcher_, &ThreadWatcher::DeActivateThreadWatching));
462 547
463 // Wait for the io_watcher_'s VeryLongMethod to finish. 548 // Wait for the io_watcher_'s VeryLongMethod to finish.
464 io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE); 549 io_watcher_->WaitForWaitStateChange(kUnresponsiveTime * 10, ALL_DONE);
465 } 550 }
OLDNEW
« no previous file with comments | « chrome/browser/metrics/thread_watcher.cc ('k') | chrome/common/chrome_switches.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698