test_utils.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 3// found in the LICENSE file. 4 5#include "content/public/test/test_utils.h" 6 7#include "base/bind.h" 8#include "base/message_loop.h" 9#include "base/run_loop.h" 10#include "content/public/browser/notification_service.h" 11#include "content/public/test/test_launcher.h" 12#include "testing/gtest/include/gtest/gtest.h" 13 14namespace content { 15 16namespace { 17 18// Number of times to repost a Quit task so that the MessageLoop finishes up 19// pending tasks and tasks posted by those pending tasks without risking the 20// potential hang behavior of MessageLoop::QuitWhenIdle. 21// The criteria for choosing this number: it should be high enough to make the 22// quit act like QuitWhenIdle, while taking into account that any page which is 23// animating may be rendering another frame for each quit deferral. For an 24// animating page, the potential delay to quitting the RunLoop would be 25// kNumQuitDeferrals * frame_render_time. Some perf tests run slow, such as 26// 200ms/frame. 27static const int kNumQuitDeferrals = 10; 28 29static void DeferredQuitRunLoop(const base::Closure& quit_task, 30 int num_quit_deferrals) { 31 if (num_quit_deferrals <= 0) { 32 quit_task.Run(); 33 } else { 34 MessageLoop::current()->PostTask(FROM_HERE, 35 base::Bind(&DeferredQuitRunLoop, quit_task, num_quit_deferrals - 1)); 36 } 37} 38 39void RunAllPendingMessageAndSendQuit(BrowserThread::ID thread_id, 40 const base::Closure& quit_task) { 41 RunAllPendingInMessageLoop(); 42 BrowserThread::PostTask(thread_id, FROM_HERE, quit_task); 43} 44 45} // namespace 46 47void RunMessageLoop() { 48 base::RunLoop run_loop; 49 RunThisRunLoop(&run_loop); 50} 51 52void RunThisRunLoop(base::RunLoop* run_loop) { 53 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); 54 55 // If we're running inside a browser test, we might need to allow the test 56 // launcher to do extra work before/after running a nested message loop. 57 TestLauncherDelegate* delegate = GetCurrentTestLauncherDelegate(); 58 if (delegate) 59 delegate->PreRunMessageLoop(run_loop); 60 run_loop->Run(); 61 if (delegate) 62 delegate->PostRunMessageLoop(); 63} 64 65void RunAllPendingInMessageLoop() { 66 MessageLoop::current()->PostTask(FROM_HERE, 67 MessageLoop::QuitWhenIdleClosure()); 68 RunMessageLoop(); 69} 70 71void RunAllPendingInMessageLoop(BrowserThread::ID thread_id) { 72 if (BrowserThread::CurrentlyOn(thread_id)) { 73 RunAllPendingInMessageLoop(); 74 return; 75 } 76 BrowserThread::ID current_thread_id; 77 if (!BrowserThread::GetCurrentThreadIdentifier(¤t_thread_id)) { 78 NOTREACHED(); 79 return; 80 } 81 82 base::RunLoop run_loop; 83 BrowserThread::PostTask(thread_id, FROM_HERE, 84 base::Bind(&RunAllPendingMessageAndSendQuit, current_thread_id, 85 run_loop.QuitClosure())); 86 RunThisRunLoop(&run_loop); 87} 88 89base::Closure GetQuitTaskForRunLoop(base::RunLoop* run_loop) { 90 return base::Bind(&DeferredQuitRunLoop, run_loop->QuitClosure(), 91 kNumQuitDeferrals); 92} 93 94MessageLoopRunner::MessageLoopRunner() { 95} 96 97MessageLoopRunner::~MessageLoopRunner() { 98} 99 100void MessageLoopRunner::Run() { 101 RunThisRunLoop(&run_loop_); 102} 103 104base::Closure MessageLoopRunner::QuitClosure() { 105 return base::Bind(&MessageLoopRunner::Quit, this); 106} 107 108void MessageLoopRunner::Quit() { 109 GetQuitTaskForRunLoop(&run_loop_).Run(); 110} 111 112WindowedNotificationObserver::WindowedNotificationObserver( 113 int notification_type, 114 const NotificationSource& source) 115 : seen_(false), 116 running_(false), 117 source_(NotificationService::AllSources()) { 118 registrar_.Add(this, notification_type, source); 119} 120 121WindowedNotificationObserver::~WindowedNotificationObserver() {} 122 123void WindowedNotificationObserver::Wait() { 124 if (seen_) 125 return; 126 127 running_ = true; 128 message_loop_runner_ = new MessageLoopRunner; 129 message_loop_runner_->Run(); 130 EXPECT_TRUE(seen_); 131} 132 133void WindowedNotificationObserver::Observe( 134 int type, 135 const NotificationSource& source, 136 const NotificationDetails& details) { 137 source_ = source; 138 details_ = details; 139 seen_ = true; 140 if (!running_) 141 return; 142 143 message_loop_runner_->Quit(); 144 running_ = false; 145} 146 147} // namespace content 148