test_utils.h revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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#ifndef CONTENT_PUBLIC_TEST_TEST_UTILS_H_ 6#define CONTENT_PUBLIC_TEST_TEST_UTILS_H_ 7 8#include "base/callback.h" 9#include "base/memory/ref_counted.h" 10#include "base/memory/scoped_ptr.h" 11#include "base/run_loop.h" 12#include "content/public/browser/browser_child_process_observer.h" 13#include "content/public/browser/browser_thread.h" 14#include "content/public/browser/notification_details.h" 15#include "content/public/browser/notification_observer.h" 16#include "content/public/browser/notification_registrar.h" 17#include "content/public/browser/notification_source.h" 18 19namespace base { 20class Value; 21} 22 23// A collection of functions designed for use with unit and browser tests. 24 25namespace content { 26 27class RenderViewHost; 28 29// Turns on nestable tasks, runs the message loop, then resets nestable tasks 30// to what they were originally. Prefer this over MessageLoop::Run for in 31// process browser tests that need to block until a condition is met. 32void RunMessageLoop(); 33 34// Variant of RunMessageLoop that takes RunLoop. 35void RunThisRunLoop(base::RunLoop* run_loop); 36 37// Turns on nestable tasks, runs all pending tasks in the message loop, 38// then resets nestable tasks to what they were originally. Prefer this 39// over MessageLoop::RunAllPending for in process browser tests to run 40// all pending tasks. 41void RunAllPendingInMessageLoop(); 42 43// Blocks the current thread until all the pending messages in the loop of the 44// thread |thread_id| have been processed. 45void RunAllPendingInMessageLoop(BrowserThread::ID thread_id); 46 47// Get task to quit the given RunLoop. It allows a few generations of pending 48// tasks to run as opposed to run_loop->QuitClosure(). 49base::Closure GetQuitTaskForRunLoop(base::RunLoop* run_loop); 50 51// Executes the specified javascript in the top-level frame, and runs a nested 52// MessageLoop. When the result is available, it is returned. 53// This should not be used; the use of the ExecuteScript functions in 54// browser_test_utils is preferable. 55scoped_ptr<base::Value> ExecuteScriptAndGetValue( 56 RenderViewHost* render_view_host, 57 const std::string& script); 58 59// Helper class to Run and Quit the message loop. Run and Quit can only happen 60// once per instance. Make a new instance for each use. Calling Quit after Run 61// has returned is safe and has no effect. 62class MessageLoopRunner : public base::RefCounted<MessageLoopRunner> { 63 public: 64 MessageLoopRunner(); 65 66 // Run the current MessageLoop unless the quit closure 67 // has already been called. 68 void Run(); 69 70 // Quit the matching call to Run (nested MessageLoops are unaffected). 71 void Quit(); 72 73 // Hand this closure off to code that uses callbacks to notify completion. 74 // Example: 75 // scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner; 76 // kick_off_some_api(runner->QuitClosure()); 77 // runner->Run(); 78 base::Closure QuitClosure(); 79 80 private: 81 friend class base::RefCounted<MessageLoopRunner>; 82 ~MessageLoopRunner(); 83 84 // True when the message loop is running. 85 bool loop_running_; 86 87 // True after closure returned by |QuitClosure| has been called. 88 bool quit_closure_called_; 89 90 base::RunLoop run_loop_; 91 92 DISALLOW_COPY_AND_ASSIGN(MessageLoopRunner); 93}; 94 95// A WindowedNotificationObserver allows code to wait until a condition is met. 96// Simple conditions are specified by providing a |notification_type| and a 97// |source|. When a notification of the expected type from the expected source 98// is received, the condition is met. 99// More complex conditions can be specified by providing a |notification_type| 100// and a |callback|. The callback is called whenever the notification is fired. 101// If the callback returns |true|, the condition is met. Otherwise, the 102// condition is not yet met and the callback will be invoked again every time a 103// notification of the expected type is received until the callback returns 104// |true|. For convenience, two callback types are defined, one that is provided 105// with the notification source and details, and one that is not. 106// 107// This helper class exists to avoid the following common pattern in tests: 108// PerformAction() 109// WaitForCompletionNotification() 110// The pattern leads to flakiness as there is a window between PerformAction 111// returning and the observers getting registered, where a notification will be 112// missed. 113// 114// Rather, one can do this: 115// WindowedNotificationObserver signal(...) 116// PerformAction() 117// signal.Wait() 118class WindowedNotificationObserver : public NotificationObserver { 119 public: 120 // Callback invoked on notifications. Should return |true| when the condition 121 // being waited for is met. For convenience, there is a choice between two 122 // callback types, one that is provided with the notification source and 123 // details, and one that is not. 124 typedef base::Callback<bool(const NotificationSource&, 125 const NotificationDetails&)> 126 ConditionTestCallback; 127 typedef base::Callback<bool(void)> 128 ConditionTestCallbackWithoutSourceAndDetails; 129 130 // Set up to wait for a simple condition. The condition is met when a 131 // notification of the given |notification_type| from the given |source| is 132 // received. To accept notifications from all sources, specify 133 // NotificationService::AllSources() as |source|. 134 WindowedNotificationObserver(int notification_type, 135 const NotificationSource& source); 136 137 // Set up to wait for a complex condition. The condition is met when 138 // |callback| returns |true|. The callback is invoked whenever a notification 139 // of |notification_type| from any source is received. 140 WindowedNotificationObserver(int notification_type, 141 const ConditionTestCallback& callback); 142 WindowedNotificationObserver( 143 int notification_type, 144 const ConditionTestCallbackWithoutSourceAndDetails& callback); 145 146 virtual ~WindowedNotificationObserver(); 147 148 // Adds an additional notification type to wait for. The condition will be met 149 // if any of the registered notification types from their respective sources 150 // is received. 151 void AddNotificationType(int notification_type, 152 const NotificationSource& source); 153 154 // Wait until the specified condition is met. If the condition is already met 155 // (that is, the expected notification has already been received or the 156 // given callback returns |true| already), Wait() returns immediately. 157 void Wait(); 158 159 // Returns NotificationService::AllSources() if we haven't observed a 160 // notification yet. 161 const NotificationSource& source() const { 162 return source_; 163 } 164 165 const NotificationDetails& details() const { 166 return details_; 167 } 168 169 // NotificationObserver: 170 virtual void Observe(int type, 171 const NotificationSource& source, 172 const NotificationDetails& details) OVERRIDE; 173 174 private: 175 bool seen_; 176 bool running_; 177 NotificationRegistrar registrar_; 178 179 ConditionTestCallback callback_; 180 181 NotificationSource source_; 182 NotificationDetails details_; 183 scoped_refptr<MessageLoopRunner> message_loop_runner_; 184 185 DISALLOW_COPY_AND_ASSIGN(WindowedNotificationObserver); 186}; 187 188// Unit tests can use code which runs in the utility process by having it run on 189// an in-process utility thread. This eliminates having two code paths in 190// production code to deal with unit tests, and also helps with the binary 191// separation on Windows since chrome.dll doesn't need to call into Blink code 192// for some utility code to handle the single process case. 193// Include this class as a member variable in your test harness if you take 194// advantage of this functionality to ensure that the in-process utility thread 195// is torn down correctly. See http://crbug.com/316919 for more information. 196// Note: this class should be declared after the TestBrowserThreadBundle and 197// ShadowingAtExitManager (if it exists) as it will need to be run before they 198// are torn down. 199class InProcessUtilityThreadHelper : public BrowserChildProcessObserver { 200 public: 201 InProcessUtilityThreadHelper(); 202 virtual ~InProcessUtilityThreadHelper(); 203 204 private: 205 virtual void BrowserChildProcessHostConnected( 206 const ChildProcessData& data) OVERRIDE; 207 virtual void BrowserChildProcessHostDisconnected( 208 const ChildProcessData& data) OVERRIDE; 209 210 int child_thread_count_; 211 scoped_refptr<MessageLoopRunner> runner_; 212 213 DISALLOW_COPY_AND_ASSIGN(InProcessUtilityThreadHelper); 214}; 215 216} // namespace content 217 218#endif // CONTENT_PUBLIC_TEST_TEST_UTILS_H_ 219