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