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.
5 #ifndef CHROME_TEST_BASE_VIEW_EVENT_TEST_BASE_H_
6 #define CHROME_TEST_BASE_VIEW_EVENT_TEST_BASE_H_
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)
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"
24 #include "ui/base/win/scoped_ole_initializer.h"
41 // Base class for Views based tests that dispatch events.
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
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.
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.
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.
63 // Once you have created a ViewEventTestBase use the macro VIEW_TEST to define
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
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);
78 class ViewEventTestBase
: public views::WidgetDelegate
,
79 public testing::Test
{
83 // Invoke when done either because of failure or success. Quits the message
87 static void SetUpTestCase();
90 virtual void SetUp() OVERRIDE
;
92 // Destroys the window.
93 virtual void TearDown() OVERRIDE
;
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
;
101 // Overridden to do nothing so that this class can be used in runnable tasks.
106 virtual ~ViewEventTestBase();
108 // Returns the view that is added to the window.
109 virtual views::View
* CreateContentsView() = 0;
111 // Called once the message loop is running.
112 virtual void DoTestOnMessageLoop() = 0;
114 // Invoke from test main. Shows the window, starts the message loop and
115 // schedules a task that invokes DoTestOnMessageLoop.
116 void StartMessageLoopAndRunTest();
118 // Returns an empty Size. Subclasses that want a preferred size other than
119 // that of the View returned by CreateContentsView should override this
121 virtual gfx::Size
GetPreferredSize();
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
126 template <class T
, class Method
>
127 base::Closure
CreateEventTask(T
* target
, Method method
) {
128 return base::Bind(&ViewEventTestBase::RunTestMethod
, this,
129 base::Bind(method
, target
));
132 // Spawns a new thread posts a MouseMove in the background.
133 void ScheduleMouseMoveInBackground(int x
, int y
);
135 views::Widget
* window_
;
138 // Stops the thread started by ScheduleMouseMoveInBackground.
139 void StopBackgroundThread();
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
);
145 // The content of the Window.
146 views::View
* content_view_
;
148 // Thread for posting background MouseMoves.
149 scoped_ptr
<base::Thread
> dnd_thread_
;
151 content::TestBrowserThreadBundle thread_bundle_
;
154 ui::ScopedOleInitializer ole_initializer_
;
157 #if defined(USE_AURA)
158 scoped_ptr
<aura::test::AuraTestHelper
> aura_test_helper_
;
159 scoped_ptr
<wm::WMState
> wm_state_
;
162 ChromeViewsDelegate views_delegate_
;
164 DISALLOW_COPY_AND_ASSIGN(ViewEventTestBase
);
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();\
174 #endif // defined(HAS_OUT_OF_PROC_TEST_RUNNER)
176 #endif // CHROME_TEST_BASE_VIEW_EVENT_TEST_BASE_H_