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