test_utils.h revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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#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 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 encapsulates the logic that determines whether
101// the condition has been met. If the callback returns |true|, the condition is
102// met. Otherwise, the condition is not yet met and the callback will be invoked
103// again every time a notification of the expected type is received until the
104// callback returns |true|.
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()
117class WindowedNotificationObserver : public NotificationObserver {
118 public:
119  // Callback invoked on notifications. Should return |true| when the condition
120  // being waited for is met.
121  typedef base::Callback<bool(void)> ConditionTestCallback;
122
123  // Set up to wait for a simple condition. The condition is met when a
124  // notification of the given |notification_type| from the given |source| is
125  // received. To accept notifications from all sources, specify
126  // NotificationService::AllSources() as |source|.
127  WindowedNotificationObserver(int notification_type,
128                               const NotificationSource& source);
129
130  // Set up to wait for a complex condition. The condition is met when
131  // |callback| returns |true|. The callback is invoked whenever a notification
132  // of |notification_type| from any source is received.
133  WindowedNotificationObserver(int notification_type,
134                               const ConditionTestCallback& callback);
135
136  virtual ~WindowedNotificationObserver();
137
138  // Wait until the specified condition is met. If the condition is already met
139  // (that is, the expected notification has already been received or the
140  // given callback returns |true| already), Wait() returns immediately.
141  void Wait();
142
143  // Returns NotificationService::AllSources() if we haven't observed a
144  // notification yet.
145  const NotificationSource& source() const {
146    return source_;
147  }
148
149  const NotificationDetails& details() const {
150    return details_;
151  }
152
153  // NotificationObserver:
154  virtual void Observe(int type,
155                       const NotificationSource& source,
156                       const NotificationDetails& details) OVERRIDE;
157
158 private:
159  bool seen_;
160  bool running_;
161  NotificationRegistrar registrar_;
162
163  ConditionTestCallback callback_;
164
165  NotificationSource source_;
166  NotificationDetails details_;
167  scoped_refptr<MessageLoopRunner> message_loop_runner_;
168
169  DISALLOW_COPY_AND_ASSIGN(WindowedNotificationObserver);
170};
171
172}  // namespace content
173
174#endif  // CONTENT_PUBLIC_TEST_TEST_UTILS_H_
175