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