test_utils.h revision 868fa2fe829687343ffae624259930155e16dbd8
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_forward.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_thread.h" 13#include "content/public/browser/notification_details.h" 14#include "content/public/browser/notification_observer.h" 15#include "content/public/browser/notification_registrar.h" 16#include "content/public/browser/notification_source.h" 17#include "googleurl/src/gurl.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// Adds pre/post hooks to call when running a message loop. 38// DEPRECATED: Please do not use in new code. 39// TODO(phajdan.jr): Remove message loop hooks after switch to Aura. 40typedef base::Callback<void(base::RunLoop*)> RunMessageLoopHook; 41void AddPreRunMessageLoopHook(const RunMessageLoopHook& hook); 42void AddPostRunMessageLoopHook(const RunMessageLoopHook& hook); 43 44// Turns on nestable tasks, runs all pending tasks in the message loop, 45// then resets nestable tasks to what they were originally. Prefer this 46// over MessageLoop::RunAllPending for in process browser tests to run 47// all pending tasks. 48void RunAllPendingInMessageLoop(); 49 50// Blocks the current thread until all the pending messages in the loop of the 51// thread |thread_id| have been processed. 52void RunAllPendingInMessageLoop(BrowserThread::ID thread_id); 53 54// Get task to quit the given RunLoop. It allows a few generations of pending 55// tasks to run as opposed to run_loop->QuitClosure(). 56base::Closure GetQuitTaskForRunLoop(base::RunLoop* run_loop); 57 58// Executes the specified javascript in the top-level frame, and runs a nested 59// MessageLoop. When the result is available, it is returned. 60// This should not be used; the use of the ExecuteScript functions in 61// browser_test_utils is preferable. 62scoped_ptr<base::Value> ExecuteScriptAndGetValue( 63 RenderViewHost* render_view_host, 64 const std::string& script); 65 66// Helper class to Run and Quit the message loop. Run and Quit can only happen 67// once per instance. Make a new instance for each use. Calling Quit after Run 68// has returned is safe and has no effect. 69class MessageLoopRunner : public base::RefCounted<MessageLoopRunner> { 70 public: 71 MessageLoopRunner(); 72 73 // Run the current MessageLoop unless the quit closure 74 // has already been called. 75 void Run(); 76 77 // Quit the matching call to Run (nested MessageLoops are unaffected). 78 void Quit(); 79 80 // Hand this closure off to code that uses callbacks to notify completion. 81 // Example: 82 // scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner; 83 // kick_off_some_api(runner->QuitClosure()); 84 // runner->Run(); 85 base::Closure QuitClosure(); 86 87 private: 88 friend class base::RefCounted<MessageLoopRunner>; 89 ~MessageLoopRunner(); 90 91 // True when the message loop is running. 92 bool loop_running_; 93 94 // True after closure returned by |QuitClosure| has been called. 95 bool quit_closure_called_; 96 97 base::RunLoop run_loop_; 98 99 DISALLOW_COPY_AND_ASSIGN(MessageLoopRunner); 100}; 101 102// A WindowedNotificationObserver allows code to watch for a notification 103// over a window of time. Typically testing code will need to do something 104// like this: 105// PerformAction() 106// WaitForCompletionNotification() 107// This leads to flakiness as there's a window between PerformAction returning 108// and the observers getting registered, where a notification will be missed. 109// 110// Rather, one can do this: 111// WindowedNotificationObserver signal(...) 112// PerformAction() 113// signal.Wait() 114class WindowedNotificationObserver : public NotificationObserver { 115 public: 116 // Register to listen for notifications of the given type from either a 117 // specific source, or from all sources if |source| is 118 // NotificationService::AllSources(). 119 WindowedNotificationObserver(int notification_type, 120 const NotificationSource& source); 121 virtual ~WindowedNotificationObserver(); 122 123 // Wait until the specified notification occurs. If the notification was 124 // emitted between the construction of this object and this call then it 125 // returns immediately. 126 void Wait(); 127 128 // Returns NotificationService::AllSources() if we haven't observed a 129 // notification yet. 130 const NotificationSource& source() const { 131 return source_; 132 } 133 134 const NotificationDetails& details() const { 135 return details_; 136 } 137 138 // NotificationObserver: 139 virtual void Observe(int type, 140 const NotificationSource& source, 141 const NotificationDetails& details) OVERRIDE; 142 143 private: 144 bool seen_; 145 bool running_; 146 NotificationRegistrar registrar_; 147 148 NotificationSource source_; 149 NotificationDetails details_; 150 scoped_refptr<MessageLoopRunner> message_loop_runner_; 151 152 DISALLOW_COPY_AND_ASSIGN(WindowedNotificationObserver); 153}; 154 155} // namespace content 156 157#endif // CONTENT_PUBLIC_TEST_TEST_UTILS_H_ 158