- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / tabs / stacked_tab_strip_layout_unittest.cc
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.
4
5 #include "chrome/browser/ui/views/tabs/stacked_tab_strip_layout.h"
6
7 #include <string>
8
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/views/view.h"
13 #include "ui/views/view_model.h"
14
15 namespace {
16
17 struct CommonTestData {
18   const int initial_x;
19   const int width;
20   const int tab_size;
21   const int tab_padding;
22   const int stacked_offset;
23   const int mini_tab_count;
24   const int active_index;
25   const std::string start_bounds;
26   const std::string expected_bounds;
27 };
28
29 }  // namespace
30
31 class StackedTabStripLayoutTest : public testing::Test {
32  public:
33   StackedTabStripLayoutTest() {}
34
35  protected:
36   void Reset(StackedTabStripLayout* layout,
37              int x,
38              int width,
39              int mini_tab_count,
40              int active_index) {
41     layout->Reset(x, width, mini_tab_count, active_index);
42   }
43
44   void CreateLayout(const CommonTestData& data) {
45     if (!data.start_bounds.empty())
46       PrepareChildViewsFromString(data.start_bounds);
47     else
48       PrepareChildViewsFromString(data.expected_bounds);
49     layout_.reset(new StackedTabStripLayout(
50                      gfx::Size(data.tab_size, 10), data.tab_padding,
51                      data.stacked_offset, 4, &view_model_));
52     if (data.start_bounds.empty()) {
53       PrepareChildViewsFromString(data.expected_bounds);
54       layout_->Reset(data.initial_x, data.width, data.mini_tab_count,
55                      data.active_index);
56     } else {
57       ASSERT_NO_FATAL_FAILURE(SetBoundsFromString(data.start_bounds));
58       layout_->Reset(data.initial_x, data.width, data.mini_tab_count,
59                      data.active_index);
60       ASSERT_NO_FATAL_FAILURE(SetBoundsFromString(data.start_bounds));
61     }
62   }
63
64   void AddViewToViewModel(int index) {
65     views::View* child_view = new views::View;
66     view_.AddChildView(child_view);
67     view_model_.Add(child_view, index);
68   }
69
70   void PrepareChildViewsFromString(const std::string& bounds) {
71     std::vector<std::string> positions;
72     Tokenize(bounds, " ", &positions);
73     PrepareChildViews(static_cast<int>(positions.size()));
74   }
75
76   void PrepareChildViews(int count) {
77     view_model_.Clear();
78     view_.RemoveAllChildViews(true);
79     for (int i = 0; i < count; ++i)
80       AddViewToViewModel(i);
81   }
82
83   void SetBoundsFromString(const std::string& bounds) {
84     std::vector<std::string> positions;
85     Tokenize(bounds, " ", &positions);
86     PrepareChildViews(static_cast<int>(positions.size()));
87     for (int i = 0; i < view_model_.view_size(); ++i) {
88       int x = 0;
89       gfx::Rect bounds(view_model_.ideal_bounds(i));
90       ASSERT_TRUE(base::StringToInt(positions[i], &x));
91       bounds.set_x(x);
92       view_model_.set_ideal_bounds(i, bounds);
93     }
94   }
95
96   std::string BoundsString() const {
97     std::string result;
98     for (int i = 0; i < view_model_.view_size(); ++i) {
99       if (!result.empty())
100         result += " ";
101       result += base::IntToString(view_model_.ideal_bounds(i).x());
102     }
103     return result;
104   }
105
106   std::string BoundsString2(int active_index) const {
107     std::string result;
108     for (int i = 0; i < view_model_.view_size(); ++i) {
109       if (!result.empty())
110         result += " ";
111       if (i == active_index)
112         result += "[";
113       result += base::IntToString(view_model_.ideal_bounds(i).x());
114       if (i == active_index)
115         result += "]";
116     }
117     return result;
118   }
119
120   void Validate(int active_index, int max_width) {
121     // Make sure none of the tabs are more than 90 apart
122     // (tab_size(100) + padding (-10)).
123     for (int j = 1; j < view_model_.view_size(); ++j)
124       EXPECT_LE(ideal_x(j) - ideal_x(j - 1), max_width - 100);
125   }
126
127   int ideal_x(int index) const {
128     return view_model_.ideal_bounds(index).x();
129   }
130
131   scoped_ptr<StackedTabStripLayout> layout_;
132   views::ViewModel view_model_;
133
134  private:
135   views::View view_;
136
137   DISALLOW_COPY_AND_ASSIGN(StackedTabStripLayoutTest);
138 };
139
140 // Random data.
141 TEST_F(StackedTabStripLayoutTest, ValidateInitialLayout) {
142   StackedTabStripLayout layout(gfx::Size(100, 10), -10, 2, 4, &view_model_);
143   PrepareChildViews(12);
144
145   for (int i = 120; i < 600; ++i) {
146     for (int j = 0; j < 12; ++j) {
147       Reset(&layout, 0, i, 0, j);
148       Validate(j, i);
149       if (HasNonfatalFailure())
150         return;
151     }
152   }
153 }
154
155 // Ensure initial layout is correct.
156 TEST_F(StackedTabStripLayoutTest, InitialLayout) {
157   struct CommonTestData test_data[] = {
158     { 0, 198, 100, -10, 1, 0, 9, "",
159       "0 0 0 0 0 0 1 2 3 4 94 95 96 97 98 98 98 98" },
160     { 0, 198, 100, -10, 1, 0, 0, "", "0 90 94 95 96 97 98 98 98" },
161     { 0, 300, 100, -10, 1, 0, 0, "",
162       "0 90 180 196 197 198 199 200 200 200 200" },
163     { 0, 300, 100, -10, 1, 0, 10, "", "0 0 0 0 1 2 3 4 20 110 200" },
164     { 0, 300, 100, -10, 1, 0, 1, "", "0 90 180 196 197 198 199 200 200" },
165     { 0, 643, 160, -27, 6, 0, 0, "", "0 133 266 399" },
166     { 0, 300, 100, -10, 1, 0, 7, "", "0 1 2 3 4 20 110 200" },
167     { 0, 300, 100, -10, 1, 0, 6, "", "0 1 2 3 4 20 110 200" },
168     { 0, 300, 100, -10, 1, 0, 4, "", "0 1 2 3 4 94 184 199 200" },
169   };
170   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
171     CreateLayout(test_data[i]);
172     EXPECT_EQ(test_data[i].expected_bounds, BoundsString()) << " at " << i;
173   }
174 }
175
176 // Assertions for dragging from an existing configuration.
177 TEST_F(StackedTabStripLayoutTest, DragActiveTabExisting) {
178   struct TestData {
179     struct CommonTestData common_data;
180     const int delta;
181   } test_data[] = {
182     //
183     // The following set of tests create 6 tabs, the first two are pinned and
184     // the 2nd tab is selected.
185     //
186     // 1 pixel to the right, should push only mini-tabs and first non-mini-tab.
187     { { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140",
188         "1 6 11 101 138 140" }, 1 },
189     // Push enough to collapse the 4th tab.
190     { { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140",
191         "36 41 46 136 138 140" }, 36 },
192     // 1 past collapsing the 4th.
193     { { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140",
194         "37 42 47 136 138 140" }, 37 },
195     // Collapse the third.
196     { { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140",
197         "124 129 134 136 138 140" }, 124 },
198     // One past collapsing the third.
199     { { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140",
200         "124 129 134 136 138 140" }, 125 },
201
202     //
203     // The following set of tests create 6 tabs, the first two are pinned and
204     // the 5th is selected.
205     //
206     // 1 pixel to the right, should expose part of a tab.
207     { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", "0 5 10 90 131 140" },
208       1 },
209     // Push the tab as far to the right as it'll go.
210     { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", "0 5 10 90 138 140" },
211       8 },
212     // One past as far to the right as it'll go. Should expose more of the tab
213     // before it.
214     { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", "0 5 10 91 138 140" },
215       9 },
216     // Enough so that the pinned tabs start pulling in.
217     { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", "1 6 11 101 138 140" },
218       19 },
219     // One more than last.
220     { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", "2 7 12 102 138 140" },
221       20 },
222     // Enough to collapse the fourth as small it can get.
223     { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140",
224         "36 41 46 136 138 140" }, 54 },
225     // Enough to collapse the third as small it can get.
226     { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140",
227         "124 129 134 136 138 140" }, 142 },
228     // One more than last, shouldn't change anything.
229     { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140",
230         "124 129 134 136 138 140" }, 143 },
231
232     //
233     // The following set of tests create 3 tabs with the second selected.
234     //
235     // Drags in 2, pulling the rightmost tab along.
236     { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "2 92 140" }, 2 },
237     // Drags the rightmost tab as far to right as possible.
238     { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "48 138 140" }, 48 },
239     // Drags so much that the left most tabs pulls in.
240     { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "135 138 140" }, 135 },
241     // Drags so far that no more tabs pull in.
242     { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "136 138 140" }, 200 },
243     // Drags to the left most position before the right tabs start pulling in.
244     { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "0 50 140" }, -40 },
245     // Drags 1 beyond the left most position, which should pull in the right
246     // tab slightly.
247     { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "0 49 139" }, -41 },
248     // Drags to the left as far as the tab goes.
249     { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "0 2 92" }, -88 },
250     // Drags one past as far to the left as the tab goes. Should keep pulling
251     // in the rightmost tab.
252     { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "0 2 91" }, -89 },
253   };
254
255   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
256     CreateLayout(test_data[i].common_data);
257     layout_->DragActiveTab(test_data[i].delta);
258     EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) <<
259         " at " << i;
260   }
261 }
262
263 // Assertions for SizeToFit().
264 TEST_F(StackedTabStripLayoutTest, SizeToFit) {
265   struct CommonTestData test_data[] = {
266     // Dragged to the right.
267     { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140", "1 6 11 101 138 140"},
268     { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140",
269       "124 129 134 136 138 140" },
270
271     // Dragged to the left.
272     { 0, 240, 100, -10, 2, 0, 1, "0 50 140", "0 49 139" },
273
274     // Dragged to the left.
275     { 0, 240, 100, -10, 2, 0, 1, "0 49 89 140", "0 49 89 139" },
276   };
277
278   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
279     CreateLayout(test_data[i]);
280     SetBoundsFromString(test_data[i].expected_bounds);
281     layout_->SizeToFit();
282     // NOTE: because of the way the code is structured this asserts on
283     // |start_bound|, not |expected_bounds|.
284     EXPECT_EQ(test_data[i].start_bounds, BoundsString()) << " at " << i;
285   }
286 }
287
288 // Assertions for AddTab().
289 TEST_F(StackedTabStripLayoutTest, AddTab) {
290   struct TestData {
291     CommonTestData common_data;
292     int add_index;
293     bool add_active;
294     bool add_mini;
295   } test_data[] = {
296     // Adding a background tab test cases.
297     { { 0, 300, 100, -10, 2, 0, 1, "0 90 180 198 200", "0 16 106 196 198 200"},
298       3, false, false },
299     { { 0, 300, 100, -10, 2, 0, 1, "0 90 180 198 200", "0 2 4 20 110 200"},
300       5, false, false },
301     { { 0, 300, 100, -10, 2, 0, 1, "0 90 180 198 200", "0 90 180 196 198 200"},
302       2, false, false },
303     { { 0, 300, 100, -10, 2, 0, 1, "0 90 180 198 200", "0 2 4 94 184 200"},
304       0, false, false },
305
306     { { 4, 200, 100, -10, 2, 1, 2, "0 4 10 100", "0 0 8 10 100"},
307       1, false, true },
308     { { 4, 200, 100, -10, 2, 1, 2, "0 4 10 100", "0 0 8 98 100"},
309       1, true, true },
310     { { 4, 200, 100, -10, 2, 1, 2, "0 4 10 100", "0 0 8 98 100"},
311       0, true, true },
312     { { 0, 200, 100, -10, 2, 0, 2, "0 2 10 100", "0 4 94 98 100"},
313       0, true, true },
314
315     { { 0, 200, 100, -10, 2, 0, 0, "0 90 92 92 94 96 98 100",
316                                    "0 0 0 2 4 6 8 98 100"},
317       7, true, false },
318     { { 0, 200, 100, -10, 2, 0, 7, "0 2 4 6 8 8 10 100",
319                                    "0 0 2 4 6 8 96 98 100"},
320       5, true, false },
321     { { 0, 200, 100, -10, 2, 0, 7, "0 2 4 6 8 8 10 100",
322                                    "0 2 4 6 8 94 96 98 100"},
323       4, true, false },
324     { { 0, 200, 100, -10, 2, 0, 2, "0 2 10 100", "0 2 10 98 100"},
325       2, true, false },
326     { { 0, 200, 100, -10, 2, 0, 2, "0 2 10 100", "0 2 4 10 100"},
327       4, true, false },
328     { { 0, 200, 100, -10, 2, 0, 2, "0 2 10 100", "0 90 96 98 100"},
329       0, true, false },
330   };
331   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
332     CreateLayout(test_data[i].common_data);
333     int add_types = 0;
334     if (test_data[i].add_active)
335       add_types |= StackedTabStripLayout::kAddTypeActive;
336     if (test_data[i].add_mini)
337       add_types |= StackedTabStripLayout::kAddTypeMini;
338     AddViewToViewModel(test_data[i].add_index);
339     layout_->AddTab(test_data[i].add_index, add_types,
340                     test_data[i].common_data.initial_x +
341                     (test_data[i].add_mini ? 4 : 0));
342     EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) <<
343         " at " << i;
344   }
345 }
346
347 // Assertions around removing tabs.
348 TEST_F(StackedTabStripLayoutTest, RemoveTab) {
349   // TODO: add coverage of removing mini tabs!
350   struct TestData {
351     struct CommonTestData common_data;
352     const int remove_index;
353     const int x_after_remove;
354   } test_data[] = {
355     { { 0, 882, 220, -29, 2, 0, 4, "0 23 214 405 596 602",
356         "0 191 382 573 662" }, 1, 0 },
357
358     // Remove before active.
359     { { 0, 200, 100, -10, 2, 0, 4, "0 2 4 6 8 10 80 98 100",
360         "0 2 6 8 10 80 98 100" },
361       2, 0 },
362
363     // Stacked tabs on both sides.
364     { { 0, 200, 100, -10, 2, 0, 4, "0 2 4 6 8 10 80 98 100",
365         "0 2 4 6 10 80 98 100" },
366       4, 0 },
367
368     // Mini-tabs.
369     { { 8, 200, 100, -10, 2, 1, 0, "0 8 94 96 98 100", "0 86 88 90 100" },
370       0, 0 },
371     { { 16, 200, 100, -10, 2, 2, 0, "0 8 16 94 96 98 100", "8 8 86 88 90 100" },
372       0, 8 },
373     { { 16, 200, 100, -10, 2, 2, 0, "0 8 16 94 96 98 100", "0 8 86 88 90 100" },
374       1, 8 },
375
376     // Remove from ideal layout.
377     { { 0, 200, 100, -10, 2, 0, 0, "0 90 94 96 98 100", "0 90 96 98 100" },
378       0, 0 },
379     { { 0, 200, 100, -10, 2, 0, 0, "0 90 94 96 98 100", "0 90 96 98 100" },
380       1, 0 },
381     { { 0, 200, 100, -10, 2, 0, 0, "0 90 94 96 98 100", "0 90 96 98 100" },
382       2, 0 },
383     { { 0, 200, 100, -10, 2, 0, 0, "0 90 94 96 98 100", "0 90 94 98 100" },
384       3, 0 },
385     { { 0, 200, 100, -10, 2, 0, 0, "0 90 94 96 98 100", "0 90 94 96 100" },
386       5, 0 },
387   };
388   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
389     CreateLayout(test_data[i].common_data);
390     int old_x = view_model_.ideal_bounds(test_data[i].remove_index).x();
391     view_model_.Remove(test_data[i].remove_index);
392     layout_->RemoveTab(test_data[i].remove_index, test_data[i].x_after_remove,
393                        old_x);
394     EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) <<
395         " at " << i;
396   }
397 }
398
399 // Assertions for SetWidth().
400 TEST_F(StackedTabStripLayoutTest, SetWidth) {
401   struct TestData {
402     CommonTestData common_data;
403     int new_width;
404   } test_data[] = {
405     { { 0, 500, 100, -10, 2, 0, 4, "0 90 180 270 360 400",
406                                    "0 90 180 196 198 200"}, 300 },
407
408     // Verifies a bug in AdjustTrailingStackedTabs().
409     { { 0, 103, 100, -10, 2, 0, 0, "", "0 2"}, 102 },
410
411     { { 8, 250, 100, -10, 2, 2, 2, "0 4 8 98 148 150", "0 4 8 98 160 250"},
412       350 },
413     { { 8, 250, 100, -10, 2, 2, 2, "0 4 8 98 148 150", "0 4 8 96 98 100"},
414       200 },
415
416     { { 0, 250, 100, -10, 2, 0, 2, "0 40 90 120 150", "0 40 90 98 100"}, 200 },
417     { { 0, 250, 100, -10, 2, 0, 2, "0 2 60 150", "0 2 60 100"}, 200 },
418     { { 0, 250, 100, -10, 2, 0, 2, "0 40 120 150", "0 40 98 100"}, 200 },
419
420     { { 0, 200, 100, -10, 2, 0, 2, "0 2 10 100", "0 2 60 150"}, 250 },
421     { { 0, 200, 100, -10, 2, 0, 2, "0 2 4 10 100", "0 2 20 110 200"}, 300 },
422   };
423   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
424     CreateLayout(test_data[i].common_data);
425     layout_->SetWidth(test_data[i].new_width);
426     EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) <<
427         " at " << i;
428   }
429 }
430
431 // Assertions for SetActiveIndex().
432 TEST_F(StackedTabStripLayoutTest, SetActiveIndex) {
433   struct TestData {
434     CommonTestData common_data;
435     int new_index;
436   } test_data[] = {
437     { { 0, 250, 100, -10, 2, 0, 2, "0 4 8 98 148 150", "0 90 144 146 148 150"},
438       0 },
439     { { 0, 250, 100, -10, 2, 0, 2, "0 4 8 98 148 150", "0 2 4 58 148 150"}, 4 },
440     { { 0, 250, 100, -10, 2, 0, 2, "0 4 8 98 148 150", "0 2 4 6 60 150"}, 5 },
441     { { 4, 250, 100, -10, 2, 1, 2, "0 4 8 98 148 150", "0 4 94 146 148 150"},
442       0 },
443   };
444   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
445     CreateLayout(test_data[i].common_data);
446     layout_->SetActiveIndex(test_data[i].new_index);
447     EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) <<
448         " at " << i;
449   }
450 }
451
452 // Makes sure don't crash when resized and only one tab.
453 TEST_F(StackedTabStripLayoutTest, EmptyTest) {
454   StackedTabStripLayout layout(gfx::Size(160, 10), -27, 6, 4, &view_model_);
455   PrepareChildViews(1);
456   layout.AddTab(0, StackedTabStripLayout::kAddTypeActive, 0);
457   layout.SetWidth(100);
458   layout.SetWidth(50);
459   layout.SetWidth(0);
460   layout.SetWidth(500);
461 }
462
463 // Assertions around removing tabs.
464 TEST_F(StackedTabStripLayoutTest, MoveTab) {
465   // TODO: add coverage of removing mini tabs!
466   struct TestData {
467     struct CommonTestData common_data;
468     const int from;
469     const int to;
470     const int new_active_index;
471     const int new_start_x;
472     const int new_mini_tab_count;
473   } test_data[] = {
474     // Moves and unpins.
475     { { 10, 300, 100, -10, 2, 2, 0, "", "0 5 10 100 190 198 200" },
476       0, 1, 2, 5, 1 },
477
478     // Moves and pins.
479     { { 0, 300, 100, -10, 2, 0, 4, "", "0 5 95 185 196 198 200" },
480       2, 0, 0, 5, 1 },
481     { { 0, 300, 100, -10, 2, 1, 2, "", "0 5 10 100 190 198 200" },
482       2, 0, 0, 10, 2 },
483
484     { { 0, 200, 100, -10, 2, 0, 4, "0 2 4 6 96 98 100", "0 2 4 6 96 98 100" },
485       2, 0, 4, 0, 0 },
486     { { 0, 200, 100, -10, 2, 0, 4, "0 2 4 6 96 98 100", "0 2 4 6 8 10 100" },
487       0, 6, 6, 0, 0 },
488   };
489   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
490     CreateLayout(test_data[i].common_data);
491     view_model_.MoveViewOnly(test_data[i].from, test_data[i].to);
492     for (int j = 0; j < test_data[i].new_mini_tab_count; ++j) {
493       gfx::Rect bounds;
494       bounds.set_x(j * 5);
495       view_model_.set_ideal_bounds(j, bounds);
496     }
497     layout_->MoveTab(test_data[i].from, test_data[i].to,
498                      test_data[i].new_active_index, test_data[i].new_start_x,
499                      test_data[i].new_mini_tab_count);
500     EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) <<
501         " at " << i;
502   }
503 }
504
505 // Assertions around IsStacked().
506 TEST_F(StackedTabStripLayoutTest, IsStacked) {
507   // A single tab with enough space should never be stacked.
508   PrepareChildViews(1);
509   layout_.reset(new StackedTabStripLayout(
510                     gfx::Size(100, 10), -10, 2, 4, &view_model_));
511   Reset(layout_.get(), 0, 400, 0, 0);
512   EXPECT_FALSE(layout_->IsStacked(0));
513
514   // First tab active, remaining tabs stacked.
515   PrepareChildViews(8);
516   Reset(layout_.get(), 0, 400, 0, 0);
517   EXPECT_FALSE(layout_->IsStacked(0));
518   EXPECT_TRUE(layout_->IsStacked(7));
519
520   // Last tab active, preceeding tabs stacked.
521   layout_->SetActiveIndex(7);
522   EXPECT_FALSE(layout_->IsStacked(7));
523   EXPECT_TRUE(layout_->IsStacked(0));
524 }
525
526 // Assertions around SetXAndMiniCount.
527 TEST_F(StackedTabStripLayoutTest, SetXAndMiniCount) {
528   // Verifies we don't crash when transitioning to all mini-tabs.
529   PrepareChildViews(1);
530   layout_.reset(new StackedTabStripLayout(
531                     gfx::Size(100, 10), -10, 2, 4, &view_model_));
532   Reset(layout_.get(), 0, 400, 0, 0);
533   layout_->SetXAndMiniCount(0, 1);
534 }
535
536 // Assertions around SetXAndMiniCount.
537 TEST_F(StackedTabStripLayoutTest, SetActiveTabLocation) {
538   struct TestData {
539     struct CommonTestData common_data;
540     const int location;
541   } test_data[] = {
542     // Active tab is the first tab, can't be moved.
543     { { 0, 300, 100, -10, 2, 0, 0, "", "0 90 180 194 196 198 200" }, 50 },
544
545     // Active tab is pinned; should result in nothing.
546     { { 0, 300, 100, -10, 2, 2, 1, "", "0 0 0 90 180 198 200" }, 199 },
547
548     // Location is too far to the right, ends up being pushed in.
549     { { 0, 300, 100, -10, 2, 0, 3, "", "0 14 104 194 196 198 200" }, 199 },
550
551     // Location can be honored.
552     { { 0, 300, 100, -10, 2, 0, 3, "", "0 2 4 40 130 198 200" }, 40 },
553   };
554   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
555     CreateLayout(test_data[i].common_data);
556     layout_->SetActiveTabLocation(test_data[i].location);
557     EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) <<
558         " at " << i;
559   }
560 }