Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(301)

Side by Side Diff: ui/app_list/views/app_list_main_view_unittest.cc

Issue 298963004: app_list: Fix possible out of bounds index. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: DCHECK -> CHECK Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/app_list/test/app_list_test_model.cc ('k') | ui/app_list/views/apps_grid_view.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/app_list/views/app_list_main_view.h" 5 #include "ui/app_list/views/app_list_main_view.h"
6 6
7 #include "base/memory/scoped_ptr.h"
8 #include "base/run_loop.h"
9 #include "base/time/time.h"
10 #include "base/timer/timer.h"
7 #include "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
8 #include "ui/app_list/pagination_model.h" 12 #include "ui/app_list/pagination_model.h"
9 #include "ui/app_list/test/app_list_test_model.h" 13 #include "ui/app_list/test/app_list_test_model.h"
10 #include "ui/app_list/test/app_list_test_view_delegate.h" 14 #include "ui/app_list/test/app_list_test_view_delegate.h"
15 #include "ui/app_list/views/app_list_folder_view.h"
16 #include "ui/app_list/views/app_list_item_view.h"
11 #include "ui/app_list/views/apps_container_view.h" 17 #include "ui/app_list/views/apps_container_view.h"
12 #include "ui/app_list/views/apps_grid_view.h" 18 #include "ui/app_list/views/apps_grid_view.h"
13 #include "ui/app_list/views/contents_view.h" 19 #include "ui/app_list/views/contents_view.h"
20 #include "ui/app_list/views/test/apps_grid_view_test_api.h"
14 #include "ui/views/test/views_test_base.h" 21 #include "ui/views/test/views_test_base.h"
15 #include "ui/views/view_model.h" 22 #include "ui/views/view_model.h"
16 #include "ui/views/widget/widget.h" 23 #include "ui/views/widget/widget.h"
17 24
18 namespace app_list { 25 namespace app_list {
19 namespace test { 26 namespace test {
20 27
21 namespace { 28 namespace {
22 29
23 const int kInitialItems = 2; 30 const int kInitialItems = 2;
24 31
32 class GridViewVisibleWaiter {
33 public:
34 explicit GridViewVisibleWaiter(AppsGridView* grid_view)
35 : grid_view_(grid_view) {}
36 ~GridViewVisibleWaiter() {}
37
38 void Wait() {
39 if (grid_view_->visible())
40 return;
41
42 check_timer_.Start(FROM_HERE,
43 base::TimeDelta::FromMilliseconds(50),
44 base::Bind(&GridViewVisibleWaiter::OnTimerCheck,
45 base::Unretained(this)));
46 run_loop_.reset(new base::RunLoop);
47 run_loop_->Run();
48 check_timer_.Stop();
49 }
50
51 private:
52 void OnTimerCheck() {
53 if (grid_view_->visible())
54 run_loop_->Quit();
55 }
56
57 AppsGridView* grid_view_;
58 scoped_ptr<base::RunLoop> run_loop_;
59 base::RepeatingTimer<GridViewVisibleWaiter> check_timer_;
60
61 DISALLOW_COPY_AND_ASSIGN(GridViewVisibleWaiter);
62 };
63
25 class AppListMainViewTest : public views::ViewsTestBase { 64 class AppListMainViewTest : public views::ViewsTestBase {
26 public: 65 public:
27 AppListMainViewTest() 66 AppListMainViewTest()
28 : widget_(NULL), 67 : widget_(NULL),
29 main_view_(NULL) {} 68 main_view_(NULL) {}
30 69
31 virtual ~AppListMainViewTest() {} 70 virtual ~AppListMainViewTest() {}
32 71
33 // testing::Test overrides: 72 // testing::Test overrides:
34 virtual void SetUp() OVERRIDE { 73 virtual void SetUp() OVERRIDE {
35 views::ViewsTestBase::SetUp(); 74 views::ViewsTestBase::SetUp();
36 delegate_.reset(new AppListTestViewDelegate); 75 delegate_.reset(new AppListTestViewDelegate);
37 delegate_->GetTestModel()->PopulateApps(kInitialItems);
38 76
39 main_view_ = 77 main_view_ =
40 new AppListMainView(delegate_.get(), &pagination_model_, GetContext()); 78 new AppListMainView(delegate_.get(), &pagination_model_, GetContext());
41 main_view_->SetPaintToLayer(true); 79 main_view_->SetPaintToLayer(true);
42 80
43 widget_ = new views::Widget; 81 widget_ = new views::Widget;
44 views::Widget::InitParams params = 82 views::Widget::InitParams params =
45 CreateParams(views::Widget::InitParams::TYPE_POPUP); 83 CreateParams(views::Widget::InitParams::TYPE_POPUP);
46 params.bounds.set_size(main_view_->GetPreferredSize()); 84 params.bounds.set_size(main_view_->GetPreferredSize());
47 widget_->Init(params); 85 widget_->Init(params);
48 86
49 widget_->SetContentsView(main_view_); 87 widget_->SetContentsView(main_view_);
50 } 88 }
51 89
52 virtual void TearDown() OVERRIDE { 90 virtual void TearDown() OVERRIDE {
53 widget_->Close(); 91 widget_->Close();
54 views::ViewsTestBase::TearDown(); 92 views::ViewsTestBase::TearDown();
55 delegate_.reset(); 93 delegate_.reset();
56 } 94 }
57 95
58 const views::ViewModel* ViewModel() { 96 // |point| is in |grid_view|'s coordinates.
59 return main_view_->contents_view()->apps_container_view()->apps_grid_view() 97 AppListItemView* GetItemViewAtPointInGrid(AppsGridView* grid_view,
60 ->view_model_for_test(); 98 const gfx::Point& point) {
99 const views::ViewModel* view_model = grid_view->view_model_for_test();
100 for (int i = 0; i < view_model->view_size(); ++i) {
101 views::View* view = view_model->view_at(i);
102 if (view->bounds().Contains(point)) {
103 return static_cast<AppListItemView*>(view);
104 }
105 }
106
107 return NULL;
108 }
109
110 void SimulateClick(views::View* view) {
111 gfx::Point center = view->GetLocalBounds().CenterPoint();
112 view->OnMousePressed(ui::MouseEvent(ui::ET_MOUSE_PRESSED,
113 center,
114 center,
115 ui::EF_LEFT_MOUSE_BUTTON,
116 ui::EF_LEFT_MOUSE_BUTTON));
117 view->OnMouseReleased(ui::MouseEvent(ui::ET_MOUSE_RELEASED,
118 center,
119 center,
120 ui::EF_LEFT_MOUSE_BUTTON,
121 ui::EF_LEFT_MOUSE_BUTTON));
122 }
123
124 // |point| is in |grid_view|'s coordinates.
125 AppListItemView* SimulateInitiateDrag(AppsGridView* grid_view,
126 AppsGridView::Pointer pointer,
127 const gfx::Point& point) {
128 AppListItemView* view = GetItemViewAtPointInGrid(grid_view, point);
129 DCHECK(view);
130
131 gfx::Point translated =
132 gfx::PointAtOffsetFromOrigin(point - view->bounds().origin());
133 ui::MouseEvent pressed_event(ui::ET_MOUSE_PRESSED, translated, point, 0, 0);
134 grid_view->InitiateDrag(view, pointer, pressed_event);
135 return view;
136 }
137
138 // |point| is in |grid_view|'s coordinates.
139 void SimulateUpdateDrag(AppsGridView* grid_view,
140 AppsGridView::Pointer pointer,
141 AppListItemView* drag_view,
142 const gfx::Point& point) {
143 DCHECK(drag_view);
144 gfx::Point translated =
145 gfx::PointAtOffsetFromOrigin(point - drag_view->bounds().origin());
146 ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, translated, point, 0, 0);
147 grid_view->UpdateDragFromItem(pointer, drag_event);
148 }
149
150 AppsGridView* RootGridView() {
151 return main_view_->contents_view()->apps_container_view()->apps_grid_view();
152 }
153
154 AppListFolderView* FolderView() {
155 return main_view_->contents_view()
156 ->apps_container_view()
157 ->app_list_folder_view();
158 }
159
160 AppsGridView* FolderGridView() { return FolderView()->items_grid_view(); }
161
162 const views::ViewModel* RootViewModel() {
163 return RootGridView()->view_model_for_test();
164 }
165
166 const views::ViewModel* FolderViewModel() {
167 return FolderGridView()->view_model_for_test();
61 } 168 }
62 169
63 protected: 170 protected:
64 views::Widget* widget_; // Owned by native window. 171 views::Widget* widget_; // Owned by native window.
65 AppListMainView* main_view_; // Owned by |widget_|. 172 AppListMainView* main_view_; // Owned by |widget_|.
66 PaginationModel pagination_model_; 173 PaginationModel pagination_model_;
67 scoped_ptr<AppListTestViewDelegate> delegate_; 174 scoped_ptr<AppListTestViewDelegate> delegate_;
68 175
69 private: 176 private:
70 DISALLOW_COPY_AND_ASSIGN(AppListMainViewTest); 177 DISALLOW_COPY_AND_ASSIGN(AppListMainViewTest);
71 }; 178 };
72 179
73 } // namespace 180 } // namespace
74 181
75 // Tests changing the AppListModel when switching profiles. 182 // Tests changing the AppListModel when switching profiles.
76 TEST_F(AppListMainViewTest, ModelChanged) { 183 TEST_F(AppListMainViewTest, ModelChanged) {
77 EXPECT_EQ(kInitialItems, ViewModel()->view_size()); 184 delegate_->GetTestModel()->PopulateApps(kInitialItems);
185 EXPECT_EQ(kInitialItems, RootViewModel()->view_size());
78 186
79 // The model is owned by a profile keyed service, which is never destroyed 187 // The model is owned by a profile keyed service, which is never destroyed
80 // until after profile switching. 188 // until after profile switching.
81 scoped_ptr<AppListModel> old_model(delegate_->ReleaseTestModel()); 189 scoped_ptr<AppListModel> old_model(delegate_->ReleaseTestModel());
82 190
83 const int kReplacementItems = 5; 191 const int kReplacementItems = 5;
84 delegate_->ReplaceTestModel(kReplacementItems); 192 delegate_->ReplaceTestModel(kReplacementItems);
85 main_view_->ModelChanged(); 193 main_view_->ModelChanged();
86 EXPECT_EQ(kReplacementItems, ViewModel()->view_size()); 194 EXPECT_EQ(kReplacementItems, RootViewModel()->view_size());
195 }
196
197 // Tests dragging an item out of a single item folder and drop it at the last
198 // slot.
199 TEST_F(AppListMainViewTest, DragLastItemFromFolderAndDropAtLastSlot) {
200 // Prepare single folder with a single item in it.
201 AppListFolderItem* folder_item =
202 delegate_->GetTestModel()->CreateSingleItemFolder("single_item_folder",
203 "single");
204 EXPECT_EQ(folder_item,
205 delegate_->GetTestModel()->FindFolderItem("single_item_folder"));
206 EXPECT_EQ(AppListFolderItem::kItemType, folder_item->GetItemType());
207
208 EXPECT_EQ(1, RootViewModel()->view_size());
209 AppListItemView* folder_item_view =
210 static_cast<AppListItemView*>(RootViewModel()->view_at(0));
211 EXPECT_EQ(folder_item_view->item(), folder_item);
212 const gfx::Rect first_slot_tile = folder_item_view->bounds();
213
214 // Click on the folder to open it.
215 EXPECT_FALSE(FolderView()->visible());
216 SimulateClick(folder_item_view);
217 base::RunLoop().RunUntilIdle();
218 EXPECT_TRUE(FolderView()->visible());
219
220 #if defined(OS_WIN)
221 AppsGridViewTestApi folder_grid_view_test_api(FolderGridView());
222 folder_grid_view_test_api.DisableSynchronousDrag();
223 #endif
224
225 // Start to drag the item in folder.
226 EXPECT_EQ(1, FolderViewModel()->view_size());
227 views::View* item_view = FolderViewModel()->view_at(0);
228 gfx::Point point = item_view->bounds().CenterPoint();
229 AppListItemView* dragged =
230 SimulateInitiateDrag(FolderGridView(), AppsGridView::MOUSE, point);
231 EXPECT_EQ(item_view, dragged);
232 EXPECT_FALSE(RootGridView()->visible());
233 EXPECT_TRUE(FolderView()->visible());
234
235 // Drag it to top left corner.
236 point = gfx::Point(0, 0);
237 // Two update drags needed to actually drag the view. The first changes state
238 // and the 2nd one actually moves the view. The 2nd call can be removed when
239 // UpdateDrag is fixed.
240 SimulateUpdateDrag(FolderGridView(), AppsGridView::MOUSE, dragged, point);
241 SimulateUpdateDrag(FolderGridView(), AppsGridView::MOUSE, dragged, point);
242 base::RunLoop().RunUntilIdle();
243
244 // Wait until the folder view is invisible and root grid view shows up.
245 GridViewVisibleWaiter(RootGridView()).Wait();
246 EXPECT_TRUE(RootGridView()->visible());
247 EXPECT_EQ(0, FolderView()->layer()->opacity());
248
249 // Drop it to the slot on the right of first slot.
250 gfx::Rect drop_target_tile(first_slot_tile);
251 drop_target_tile.Offset(first_slot_tile.width(), 0);
252 point = drop_target_tile.CenterPoint();
253 SimulateUpdateDrag(FolderGridView(), AppsGridView::MOUSE, dragged, point);
254 SimulateUpdateDrag(FolderGridView(), AppsGridView::MOUSE, dragged, point);
255 base::RunLoop().RunUntilIdle();
256
257 // Drop it.
258 FolderGridView()->EndDrag(false);
259 base::RunLoop().RunUntilIdle();
260
261 // Folder icon view should be gone and there is only one item view.
262 EXPECT_EQ(1, RootViewModel()->view_size());
263 EXPECT_EQ(AppListItemView::kViewClassName,
264 RootViewModel()->view_at(0)->GetClassName());
265
266 // The item view should be in slot 1 instead of slot 2 where it is dropped.
267 AppsGridViewTestApi root_grid_view_test_api(RootGridView());
268 root_grid_view_test_api.LayoutToIdealBounds();
269 EXPECT_EQ(first_slot_tile, RootViewModel()->view_at(0)->bounds());
270
271 // Single item folder should be auto removed.
272 EXPECT_EQ(NULL,
273 delegate_->GetTestModel()->FindFolderItem("single_item_folder"));
87 } 274 }
88 275
89 } // namespace test 276 } // namespace test
90 } // namespace app_list 277 } // namespace app_list
OLDNEW
« no previous file with comments | « ui/app_list/test/app_list_test_model.cc ('k') | ui/app_list/views/apps_grid_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698