Home | History | Annotate | Download | only in test
      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 
     19 namespace base {
     20 class Value;
     21 }  // namespace base
     22 
     23 // A collection of functions designed for use with unit and browser tests.
     24 
     25 namespace content {
     26 
     27 class 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.
     32 void RunMessageLoop();
     33 
     34 // Variant of RunMessageLoop that takes RunLoop.
     35 void 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.
     41 void RunAllPendingInMessageLoop();
     42 
     43 // Blocks the current thread until all the pending messages in the loop of the
     44 // thread |thread_id| have been processed.
     45 void 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.
     49 void 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().
     53 base::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.
     59 scoped_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.
     65 class 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()
    123 class 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.
    204 class 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