Index: views/widget/widget_unittest.cc |
=================================================================== |
--- views/widget/widget_unittest.cc (revision 0) |
+++ views/widget/widget_unittest.cc (revision 0) |
@@ -0,0 +1,362 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "views/widget/native_widget_views.h" |
+ |
+#include "base/basictypes.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "views/test/test_views_delegate.h" |
+#include "views/views_delegate.h" |
+ |
+#if defined(OS_WIN) |
+#include "views/widget/native_widget_win.h" |
+#elif defined(TOOLKIT_USES_GTK) |
+#include "views/widget/native_widget_gtk.h" |
+#endif |
+ |
+namespace views { |
+namespace { |
+ |
+class WidgetTestViewsDelegate : public TestViewsDelegate { |
+ public: |
+ WidgetTestViewsDelegate() : default_parent_view_(NULL) { |
+ } |
+ virtual ~WidgetTestViewsDelegate() {} |
+ |
+ void set_default_parent_view(View* default_parent_view) { |
+ default_parent_view_ = default_parent_view; |
+ } |
+ |
+ // Overridden from TestViewsDelegate: |
+ virtual View* GetDefaultParentView() OVERRIDE { |
+ return default_parent_view_; |
+ } |
+ |
+ private: |
+ View* default_parent_view_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WidgetTestViewsDelegate); |
+}; |
+ |
+class WidgetTest : public testing::Test { |
+ public: |
+ WidgetTest() { |
+#if defined(OS_WIN) |
+ OleInitialize(NULL); |
+#endif |
+ } |
+ virtual ~WidgetTest() { |
+#if defined(OS_WIN) |
+ OleUninitialize(); |
+#endif |
+ } |
+ |
+ virtual void TearDown() { |
+ // Flush the message loop because we have pending release tasks |
+ // and these tasks if un-executed would upset Valgrind. |
+ RunPendingMessages(); |
+ } |
+ |
+ void RunPendingMessages() { |
+ message_loop_.RunAllPending(); |
+ } |
+ |
+ protected: |
+ WidgetTestViewsDelegate views_delegate; |
+ |
+ private: |
+ MessageLoopForUI message_loop_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WidgetTest); |
+}; |
+ |
+NativeWidget* CreatePlatformNativeWidget( |
+ internal::NativeWidgetDelegate* delegate) { |
+#if defined(OS_WIN) |
+ return new NativeWidgetWin(delegate); |
+#elif defined(TOOLKIT_USES_GTK) |
+ return new NativeWidgetGtk(delegate); |
+#endif |
+} |
+ |
+Widget* CreateTopLevelPlatformWidget() { |
+ Widget* toplevel = new Widget; |
+ Widget::InitParams toplevel_params(Widget::InitParams::TYPE_WINDOW); |
+ toplevel_params.native_widget = CreatePlatformNativeWidget(toplevel); |
+ toplevel->Init(toplevel_params); |
+ return toplevel; |
+} |
+ |
+Widget* CreateChildPlatformWidget(gfx::NativeView parent_native_view) { |
+ Widget* child = new Widget; |
+ Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); |
+ child_params.native_widget = CreatePlatformNativeWidget(child); |
+ child_params.parent = parent_native_view; |
+ child->Init(child_params); |
+ return child; |
+} |
+ |
+Widget* CreateChildNativeWidgetViews() { |
+ Widget* child = new Widget; |
+ Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); |
+ child_params.native_widget = new NativeWidgetViews(child); |
+ child->Init(child_params); |
+ return child; |
+} |
+ |
+TEST_F(WidgetTest, GetTopLevelWidget_Native) { |
+ // Create a hierarchy of native widgets. |
+ Widget* toplevel = CreateTopLevelPlatformWidget(); |
+#if defined(OS_WIN) |
+ gfx::NativeView parent = toplevel->GetNativeView(); |
+#elif defined(TOOLKIT_USES_GTK) |
+ NativeWidgetGtk* native_widget = |
+ static_cast<NativeWidgetGtk*>(toplevel->native_widget()); |
+ gfx::NativeView parent = native_widget->window_contents(); |
+#endif |
+ Widget* child = CreateChildPlatformWidget(parent); |
+ |
+ EXPECT_EQ(toplevel, toplevel->GetTopLevelWidget()); |
+ EXPECT_EQ(toplevel, child->GetTopLevelWidget()); |
+ |
+ toplevel->CloseNow(); |
+ // |child| should be automatically destroyed with |toplevel|. |
+} |
+ |
+TEST_F(WidgetTest, GetTopLevelWidget_Synthetic) { |
+ // Create a hierarchy consisting of a top level platform native widget and a |
+ // child NativeWidgetViews. |
+ Widget* toplevel = CreateTopLevelPlatformWidget(); |
+ views_delegate.set_default_parent_view(toplevel->GetRootView()); |
+ Widget* child = CreateChildNativeWidgetViews(); |
+ |
+ EXPECT_EQ(toplevel, toplevel->GetTopLevelWidget()); |
+ EXPECT_EQ(child, child->GetTopLevelWidget()); |
+ |
+ toplevel->CloseNow(); |
+ // |child| should be automatically destroyed with |toplevel|. |
+} |
+ |
+// TODO(beng): write test cases for child NativeWidgetViews parented to |
+// arbitrary views that aren't the default parent view. |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Widget ownership tests. |
+// |
+// Tests various permutations of Widget ownership specified in the |
+// InitParams::Ownership param. |
+ |
+// A WidgetTest that supplies a toplevel widget for NativeWidgetViews to parent |
+// to. |
+class WidgetOwnershipTest : public WidgetTest { |
+ public: |
+ WidgetOwnershipTest() {} |
+ virtual ~WidgetOwnershipTest() {} |
+ |
+ virtual void SetUp() { |
+ desktop_widget_ = CreateTopLevelPlatformWidget(); |
+ views_delegate.set_default_parent_view(desktop_widget_->GetRootView()); |
+ } |
+ |
+ virtual void TearDown() { |
+ desktop_widget_->CloseNow(); |
+ WidgetTest::TearDown(); |
+ } |
+ |
+ private: |
+ Widget* desktop_widget_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WidgetOwnershipTest); |
+}; |
+ |
+// A bag of state to monitor destructions. |
+struct OwnershipTestState { |
+ OwnershipTestState() : widget_deleted(false), native_widget_deleted(false) {} |
+ |
+ bool widget_deleted; |
+ bool native_widget_deleted; |
+}; |
+ |
+// A platform NativeWidget subclass that updates a bag of state when it is |
+// destroyed. |
+class OwnershipTestNativeWidget : |
+#if defined(OS_WIN) |
+ public NativeWidgetWin { |
+#elif defined(TOOLKIT_USES_GTK) |
+ public NativeWidgetGtk { |
+#endif |
+public: |
+ OwnershipTestNativeWidget(internal::NativeWidgetDelegate* delegate, |
+ OwnershipTestState* state) |
+#if defined(OS_WIN) |
+ : NativeWidgetWin(delegate), |
+#elif defined(TOOLKIT_USES_GTK) |
+ : NativeWidgetGtk(delegate), |
+#endif |
+ state_(state) { |
+ } |
+ virtual ~OwnershipTestNativeWidget() { |
+ state_->native_widget_deleted = true; |
+ } |
+ |
+ private: |
+ OwnershipTestState* state_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidget); |
+}; |
+ |
+// A views NativeWidget subclass that updates a bag of state when it is |
+// destroyed. |
+class OwnershipTestNativeWidgetViews : public NativeWidgetViews { |
+ public: |
+ OwnershipTestNativeWidgetViews(internal::NativeWidgetDelegate* delegate, |
+ OwnershipTestState* state) |
+ : NativeWidgetViews(delegate), |
+ state_(state) { |
+ } |
+ virtual ~OwnershipTestNativeWidgetViews() { |
+ state_->native_widget_deleted = true; |
+ } |
+ |
+ private: |
+ OwnershipTestState* state_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidgetViews); |
+}; |
+ |
+// A Widget subclass that updates a bag of state when it is destroyed. |
+class OwnershipTestWidget : public Widget { |
+ public: |
+ OwnershipTestWidget(OwnershipTestState* state) : state_(state) {} |
+ virtual ~OwnershipTestWidget() { |
+ state_->widget_deleted = true; |
+ } |
+ |
+ private: |
+ OwnershipTestState* state_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(OwnershipTestWidget); |
+}; |
+ |
+// Widget owns its NativeWidget, part 1: NativeWidget is a platform-native |
+// widget. |
+TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsPlatformNativeWidget) { |
+ OwnershipTestState state; |
+ |
+ scoped_ptr<Widget> widget(new OwnershipTestWidget(&state)); |
+ Widget::InitParams params(Widget::InitParams::TYPE_POPUP); |
+ params.native_widget = new OwnershipTestNativeWidget(widget.get(), &state); |
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
+ widget->Init(params); |
+ |
+ // Now delete the Widget, which should delete the NativeWidget. |
+ widget.reset(); |
+ |
+ EXPECT_TRUE(state.widget_deleted); |
+ EXPECT_TRUE(state.native_widget_deleted); |
+ |
+ // TODO(beng): write test for this ownership scenario and the NativeWidget |
+ // being deleted out from under the Widget. |
+} |
+ |
+// Widget owns its NativeWidget, part 2: NativeWidget is a NativeWidgetViews. |
+TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsViewsNativeWidget) { |
+ OwnershipTestState state; |
+ |
+ scoped_ptr<Widget> widget(new OwnershipTestWidget(&state)); |
+ Widget::InitParams params(Widget::InitParams::TYPE_POPUP); |
+ params.native_widget = |
+ new OwnershipTestNativeWidgetViews(widget.get(), &state); |
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
+ widget->Init(params); |
+ |
+ // Now delete the Widget, which should delete the NativeWidget. |
+ widget.reset(); |
+ |
+ EXPECT_TRUE(state.widget_deleted); |
+ EXPECT_TRUE(state.native_widget_deleted); |
+ |
+ // TODO(beng): write test for this ownership scenario and the NativeWidget |
+ // being deleted out from under the Widget. |
+} |
+ |
+// NativeWidget owns its Widget, part 1: NativeWidget is a platform-native |
+// widget. |
+TEST_F(WidgetOwnershipTest, Ownership_PlatformNativeWidgetOwnsWidget) { |
+ OwnershipTestState state; |
+ |
+ Widget* widget = new OwnershipTestWidget(&state); |
+ Widget::InitParams params(Widget::InitParams::TYPE_POPUP); |
+ params.native_widget = new OwnershipTestNativeWidget(widget, &state); |
+ widget->Init(params); |
+ |
+ // Now destroy the native widget. |
+ widget->CloseNow(); |
+ |
+ EXPECT_TRUE(state.widget_deleted); |
+ EXPECT_TRUE(state.native_widget_deleted); |
+} |
+ |
+// NativeWidget owns its Widget, part 2: NativeWidget is a NativeWidgetViews. |
+TEST_F(WidgetOwnershipTest, Ownership_ViewsNativeWidgetOwnsWidget) { |
+ OwnershipTestState state; |
+ |
+ Widget* widget = new OwnershipTestWidget(&state); |
+ Widget::InitParams params(Widget::InitParams::TYPE_POPUP); |
+ params.native_widget = new OwnershipTestNativeWidgetViews(widget, &state); |
+ widget->Init(params); |
+ |
+ // Now destroy the native widget. |
+ widget->CloseNow(); |
+ |
+ EXPECT_TRUE(state.widget_deleted); |
+ EXPECT_TRUE(state.native_widget_deleted); |
+} |
+ |
+// NativeWidget owns its Widget, part 3: NativeWidget is a platform-native |
+// widget, destroyed out from under it by the OS. |
+TEST_F(WidgetOwnershipTest, |
+ Ownership_PlatformNativeWidgetOwnsWidget_NativeDestroy) { |
+ OwnershipTestState state; |
+ |
+ Widget* widget = new OwnershipTestWidget(&state); |
+ Widget::InitParams params(Widget::InitParams::TYPE_POPUP); |
+ params.native_widget = new OwnershipTestNativeWidget(widget, &state); |
+ widget->Init(params); |
+ |
+ // Now simulate a destroy of the platform native widget from the OS: |
+#if defined(OS_WIN) |
+ DestroyWindow(widget->GetNativeView()); |
+#elif defined(TOOLKIT_USES_GTK) |
+ gtk_widget_destroy(widget->GetNativeView()); |
+#endif |
+ |
+ EXPECT_TRUE(state.widget_deleted); |
+ EXPECT_TRUE(state.native_widget_deleted); |
+} |
+ |
+// NativeWidget owns its Widget, part 4: NativeWidget is a NativeWidgetViews, |
+// destroyed by the view hierarchy that contains it. |
+TEST_F(WidgetOwnershipTest, |
+ Ownership_ViewsNativeWidgetOwnsWidget_NativeDestroy) { |
+ OwnershipTestState state; |
+ |
+ Widget* widget = new OwnershipTestWidget(&state); |
+ Widget::InitParams params(Widget::InitParams::TYPE_POPUP); |
+ params.native_widget = new OwnershipTestNativeWidgetViews(widget, &state); |
+ widget->Init(params); |
+ |
+ // Now simulate a destroy of the NativeWidgetView from its parent. |
+ NativeWidgetViews* native_widget = |
+ static_cast<NativeWidgetViews*>(widget->native_widget()); |
+ delete native_widget->GetView(); |
+ |
+ EXPECT_TRUE(state.widget_deleted); |
+ EXPECT_TRUE(state.native_widget_deleted); |
+} |
+ |
+} // namespace |
+} // namespace views |
Property changes on: views\widget\widget_unittest.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |