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