• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 CHROME_TEST_BASE_VIEW_EVENT_TEST_BASE_H_
6 #define CHROME_TEST_BASE_VIEW_EVENT_TEST_BASE_H_
7 
8 // We only want to use ViewEventTestBase in test targets which properly
9 // isolate each test case by running each test in a separate process.
10 // This way if a test hangs the test launcher can reliably terminate it.
11 #if defined(HAS_OUT_OF_PROC_TEST_RUNNER)
12 
13 #include "base/bind.h"
14 #include "base/callback.h"
15 #include "base/compiler_specific.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/threading/thread.h"
18 #include "chrome/browser/ui/views/chrome_views_delegate.h"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/views/widget/widget_delegate.h"
22 
23 #if defined(OS_WIN)
24 #include "ui/base/win/scoped_ole_initializer.h"
25 #endif
26 
27 namespace aura {
28 namespace test {
29 class AuraTestHelper;
30 }
31 }
32 
33 namespace gfx {
34 class Size;
35 }
36 
37 namespace wm {
38 class WMState;
39 }
40 
41 // Base class for Views based tests that dispatch events.
42 //
43 // As views based event test involves waiting for events to be processed,
44 // writing a views based test is slightly different than that of writing
45 // other unit tests. In particular when the test fails or is done you need
46 // to stop the message loop. This can be done by way of invoking the Done
47 // method.
48 //
49 // Any delayed callbacks should be done by way of CreateEventTask.
50 // CreateEventTask checks to see if ASSERT_XXX has been invoked after invoking
51 // the task. If there was a failure Done is invoked and the test stops.
52 //
53 // ViewEventTestBase creates a Window with the View returned from
54 // CreateContentsView. The preferred size for the view can be customized by
55 // overriding GetPreferredSize. If you do not override GetPreferredSize the
56 // preferred size of the view returned from CreateContentsView is used.
57 //
58 // Subclasses of ViewEventTestBase must implement two methods:
59 // . DoTestOnMessageLoop: invoked when the message loop is running. Run your
60 //   test here, invoke Done when done.
61 // . CreateContentsView: returns the view to place in the window.
62 //
63 // Once you have created a ViewEventTestBase use the macro VIEW_TEST to define
64 // the fixture.
65 //
66 // I encountered weird timing problems in initiating dragging and drop that
67 // necessitated ugly hacks. In particular when the hook installed by
68 // ui_controls received the mouse event and posted a task that task was not
69 // processed. To work around this use the following pattern when initiating
70 // dnd:
71 //   // Schedule the mouse move at a location slightly different from where
72 //   // you really want to move to.
73 //   ui_controls::SendMouseMoveNotifyWhenDone(loc.x + 10, loc.y,
74 //       base::Bind(&YYY, this));
75 //   // Then use this to schedule another mouse move.
76 //   ScheduleMouseMoveInBackground(loc.x, loc.y);
77 
78 class ViewEventTestBase : public views::WidgetDelegate,
79                           public testing::Test {
80  public:
81   ViewEventTestBase();
82 
83   // Invoke when done either because of failure or success. Quits the message
84   // loop.
85   void Done();
86 
87   static void SetUpTestCase();
88 
89   // Creates a window.
90   virtual void SetUp() OVERRIDE;
91 
92   // Destroys the window.
93   virtual void TearDown() OVERRIDE;
94 
95   // Overridden from views::WidgetDelegate:
96   virtual bool CanResize() const OVERRIDE;
97   virtual views::View* GetContentsView() OVERRIDE;
98   virtual const views::Widget* GetWidget() const OVERRIDE;
99   virtual views::Widget* GetWidget() OVERRIDE;
100 
101   // Overridden to do nothing so that this class can be used in runnable tasks.
AddRef()102   void AddRef() {}
Release()103   void Release() {}
104 
105  protected:
106   virtual ~ViewEventTestBase();
107 
108   // Returns the view that is added to the window.
109   virtual views::View* CreateContentsView() = 0;
110 
111   // Called once the message loop is running.
112   virtual void DoTestOnMessageLoop() = 0;
113 
114   // Invoke from test main. Shows the window, starts the message loop and
115   // schedules a task that invokes DoTestOnMessageLoop.
116   void StartMessageLoopAndRunTest();
117 
118   // Returns an empty Size. Subclasses that want a preferred size other than
119   // that of the View returned by CreateContentsView should override this
120   // appropriately.
121   virtual gfx::Size GetPreferredSize() const;
122 
123   // Creates a task that calls the specified method back. The specified
124   // method is called in such a way that if there are any test failures
125   // Done is invoked.
126   template <class T, class Method>
CreateEventTask(T * target,Method method)127   base::Closure CreateEventTask(T* target, Method method) {
128     return base::Bind(&ViewEventTestBase::RunTestMethod, this,
129                       base::Bind(method, target));
130   }
131 
132   // Spawns a new thread posts a MouseMove in the background.
133   void ScheduleMouseMoveInBackground(int x, int y);
134 
135   views::Widget* window_;
136 
137  private:
138   // Stops the thread started by ScheduleMouseMoveInBackground.
139   void StopBackgroundThread();
140 
141   // Callback from CreateEventTask. Stops the background thread, runs the
142   // supplied task and if there are failures invokes Done.
143   void RunTestMethod(const base::Closure& task);
144 
145   // The content of the Window.
146   views::View* content_view_;
147 
148   // Thread for posting background MouseMoves.
149   scoped_ptr<base::Thread> dnd_thread_;
150 
151   content::TestBrowserThreadBundle thread_bundle_;
152 
153 #if defined(OS_WIN)
154   ui::ScopedOleInitializer ole_initializer_;
155 #endif
156 
157 #if defined(USE_AURA)
158   scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
159   scoped_ptr<wm::WMState> wm_state_;
160 #endif
161 
162   ChromeViewsDelegate views_delegate_;
163 
164   DISALLOW_COPY_AND_ASSIGN(ViewEventTestBase);
165 };
166 
167 // Convenience macro for defining a ViewEventTestBase. See class description
168 // of ViewEventTestBase for details.
169 #define VIEW_TEST(test_class, name) \
170   TEST_F(test_class, name) {\
171     StartMessageLoopAndRunTest();\
172   }
173 
174 #endif  // defined(HAS_OUT_OF_PROC_TEST_RUNNER)
175 
176 #endif  // CHROME_TEST_BASE_VIEW_EVENT_TEST_BASE_H_
177