test_utils.h revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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// 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 watch for a notification 96// over a window of time. Typically testing code will need to do something 97// like this: 98// PerformAction() 99// WaitForCompletionNotification() 100// This leads to flakiness as there's a window between PerformAction returning 101// and the observers getting registered, where a notification will be missed. 102// 103// Rather, one can do this: 104// WindowedNotificationObserver signal(...) 105// PerformAction() 106// signal.Wait() 107class WindowedNotificationObserver : public NotificationObserver { 108 public: 109 // Register to listen for notifications of the given type from either a 110 // specific source, or from all sources if |source| is 111 // NotificationService::AllSources(). 112 WindowedNotificationObserver(int notification_type, 113 const NotificationSource& source); 114 virtual ~WindowedNotificationObserver(); 115 116 // Wait until the specified notification occurs. If the notification was 117 // emitted between the construction of this object and this call then it 118 // returns immediately. 119 void Wait(); 120 121 // Returns NotificationService::AllSources() if we haven't observed a 122 // notification yet. 123 const NotificationSource& source() const { 124 return source_; 125 } 126 127 const NotificationDetails& details() const { 128 return details_; 129 } 130 131 // NotificationObserver: 132 virtual void Observe(int type, 133 const NotificationSource& source, 134 const NotificationDetails& details) OVERRIDE; 135 136 private: 137 bool seen_; 138 bool running_; 139 NotificationRegistrar registrar_; 140 141 NotificationSource source_; 142 NotificationDetails details_; 143 scoped_refptr<MessageLoopRunner> message_loop_runner_; 144 145 DISALLOW_COPY_AND_ASSIGN(WindowedNotificationObserver); 146}; 147 148} // namespace content 149 150#endif // CONTENT_PUBLIC_TEST_TEST_UTILS_H_ 151