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_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|.
    104 //
    105 // This helper class exists to avoid the following common pattern in tests:
    106 //   PerformAction()
    107 //   WaitForCompletionNotification()
    108 // The pattern leads to flakiness as there is a window between PerformAction
    109 // returning and the observers getting registered, where a notification will be
    110 // missed.
    111 //
    112 // Rather, one can do this:
    113 //   WindowedNotificationObserver signal(...)
    114 //   PerformAction()
    115 //   signal.Wait()
    116 class WindowedNotificationObserver : public NotificationObserver {
    117  public:
    118   // Callback invoked on notifications. Should return |true| when the condition
    119   // being waited for is met.
    120   typedef base::Callback<bool(void)> ConditionTestCallback;
    121 
    122   // Set up to wait for a simple condition. The condition is met when a
    123   // notification of the given |notification_type| from the given |source| is
    124   // received. To accept notifications from all sources, specify
    125   // NotificationService::AllSources() as |source|.
    126   WindowedNotificationObserver(int notification_type,
    127                                const NotificationSource& source);
    128 
    129   // Set up to wait for a complex condition. The condition is met when
    130   // |callback| returns |true|. The callback is invoked whenever a notification
    131   // of |notification_type| from any source is received.
    132   WindowedNotificationObserver(int notification_type,
    133                                const ConditionTestCallback& callback);
    134 
    135   virtual ~WindowedNotificationObserver();
    136 
    137   // Wait until the specified condition is met. If the condition is already met
    138   // (that is, the expected notification has already been received or the
    139   // given callback returns |true| already), Wait() returns immediately.
    140   void Wait();
    141 
    142   // Returns NotificationService::AllSources() if we haven't observed a
    143   // notification yet.
    144   const NotificationSource& source() const {
    145     return source_;
    146   }
    147 
    148   const NotificationDetails& details() const {
    149     return details_;
    150   }
    151 
    152   // NotificationObserver:
    153   virtual void Observe(int type,
    154                        const NotificationSource& source,
    155                        const NotificationDetails& details) OVERRIDE;
    156 
    157  private:
    158   bool seen_;
    159   bool running_;
    160   NotificationRegistrar registrar_;
    161 
    162   ConditionTestCallback callback_;
    163 
    164   NotificationSource source_;
    165   NotificationDetails details_;
    166   scoped_refptr<MessageLoopRunner> message_loop_runner_;
    167 
    168   DISALLOW_COPY_AND_ASSIGN(WindowedNotificationObserver);
    169 };
    170 
    171 }  // namespace content
    172 
    173 #endif  // CONTENT_PUBLIC_TEST_TEST_UTILS_H_
    174