15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_TEST_BASE_VIEW_EVENT_TEST_BASE_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_TEST_BASE_VIEW_EVENT_TEST_BASE_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We only want to use ViewEventTestBase in test targets which properly 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// isolate each test case by running each test in a separate process. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This way if a test hangs the test launcher can reliably terminate it. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(HAS_OUT_OF_PROC_TEST_RUNNER) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/views/chrome_views_delegate.h" 19a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "content/public/test/test_browser_thread_bundle.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget_delegate.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/win/scoped_ole_initializer.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Size; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class ViewEventTestPlatformPart; 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Base class for Views based tests that dispatch events. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As views based event test involves waiting for events to be processed, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// writing a views based test is slightly different than that of writing 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// other unit tests. In particular when the test fails or is done you need 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to stop the message loop. This can be done by way of invoking the Done 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// method. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Any delayed callbacks should be done by way of CreateEventTask. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CreateEventTask checks to see if ASSERT_XXX has been invoked after invoking 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the task. If there was a failure Done is invoked and the test stops. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ViewEventTestBase creates a Window with the View returned from 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CreateContentsView. The preferred size for the view can be customized by 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// overriding GetPreferredSize. If you do not override GetPreferredSize the 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// preferred size of the view returned from CreateContentsView is used. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Subclasses of ViewEventTestBase must implement two methods: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . DoTestOnMessageLoop: invoked when the message loop is running. Run your 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// test here, invoke Done when done. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . CreateContentsView: returns the view to place in the window. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Once you have created a ViewEventTestBase use the macro VIEW_TEST to define 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the fixture. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// I encountered weird timing problems in initiating dragging and drop that 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// necessitated ugly hacks. In particular when the hook installed by 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ui_controls received the mouse event and posted a task that task was not 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// processed. To work around this use the following pattern when initiating 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dnd: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // Schedule the mouse move at a location slightly different from where 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // you really want to move to. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ui_controls::SendMouseMoveNotifyWhenDone(loc.x + 10, loc.y, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base::Bind(&YYY, this)); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // Then use this to schedule another mouse move. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ScheduleMouseMoveInBackground(loc.x, loc.y); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ViewEventTestBase : public views::WidgetDelegate, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public testing::Test { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ViewEventTestBase(); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invoke when done either because of failure or success. Quits the message 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // loop. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Done(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) static void SetUpTestCase(); 8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a window. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetUp() OVERRIDE; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Destroys the window. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() OVERRIDE; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Overridden from views::WidgetDelegate: 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool CanResize() const OVERRIDE; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual views::View* GetContentsView() OVERRIDE; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual const views::Widget* GetWidget() const OVERRIDE; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual views::Widget* GetWidget() OVERRIDE; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Overridden to do nothing so that this class can be used in runnable tasks. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddRef() {} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Release() {} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ViewEventTestBase(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the view that is added to the window. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual views::View* CreateContentsView() = 0; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called once the message loop is running. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void DoTestOnMessageLoop() = 0; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invoke from test main. Shows the window, starts the message loop and 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // schedules a task that invokes DoTestOnMessageLoop. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StartMessageLoopAndRunTest(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns an empty Size. Subclasses that want a preferred size other than 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that of the View returned by CreateContentsView should override this 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appropriately. 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual gfx::Size GetPreferredSize() const; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates a task that calls the specified method back. The specified 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // method is called in such a way that if there are any test failures 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Done is invoked. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template <class T, class Method> 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure CreateEventTask(T* target, Method method) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::Bind(&ViewEventTestBase::RunTestMethod, this, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(method, target)); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Spawns a new thread posts a MouseMove in the background. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ScheduleMouseMoveInBackground(int x, int y); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::Widget* window_; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stops the thread started by ScheduleMouseMoveInBackground. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StopBackgroundThread(); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callback from CreateEventTask. Stops the background thread, runs the 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // supplied task and if there are failures invokes Done. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RunTestMethod(const base::Closure& task); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The content of the Window. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* content_view_; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Thread for posting background MouseMoves. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Thread> dnd_thread_; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 143a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch content::TestBrowserThreadBundle thread_bundle_; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ScopedOleInitializer ole_initializer_; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_ptr<ViewEventTestPlatformPart> platform_part_; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ChromeViewsDelegate views_delegate_; 1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ViewEventTestBase); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convenience macro for defining a ViewEventTestBase. See class description 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of ViewEventTestBase for details. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VIEW_TEST(test_class, name) \ 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TEST_F(test_class, name) {\ 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartMessageLoopAndRunTest();\ 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(HAS_OUT_OF_PROC_TEST_RUNNER) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CHROME_TEST_BASE_VIEW_EVENT_TEST_BASE_H_ 166