1// Copyright (c) 2013 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 "ui/v2/public/view.h"
6
7#include "base/logging.h"
8#include "testing/gtest/include/gtest/gtest.h"
9#include "ui/compositor/layer.h"
10#include "ui/compositor/layer_type.h"
11
12namespace v2 {
13
14// View ------------------------------------------------------------------------
15
16typedef testing::Test ViewTest;
17
18TEST_F(ViewTest, AddChild) {
19  View v1;
20  View* v11 = new View;
21  v1.AddChild(v11);
22  EXPECT_EQ(1U, v1.children().size());
23}
24
25TEST_F(ViewTest, RemoveChild) {
26  View v1;
27  View* v11 = new View;
28  v1.AddChild(v11);
29  EXPECT_EQ(1U, v1.children().size());
30  v1.RemoveChild(v11);
31  EXPECT_EQ(0U, v1.children().size());
32}
33
34TEST_F(ViewTest, Reparent) {
35  View v1;
36  View v2;
37  View* v11 = new View;
38  v1.AddChild(v11);
39  EXPECT_EQ(1U, v1.children().size());
40  v2.AddChild(v11);
41  EXPECT_EQ(1U, v2.children().size());
42  EXPECT_EQ(0U, v1.children().size());
43}
44
45TEST_F(ViewTest, Contains) {
46  View v1;
47
48  // Direct descendant.
49  View* v11 = new View;
50  v1.AddChild(v11);
51  EXPECT_TRUE(v1.Contains(v11));
52
53  // Indirect descendant.
54  View* v111 = new View;
55  v11->AddChild(v111);
56  EXPECT_TRUE(v1.Contains(v111));
57}
58
59TEST_F(ViewTest, Stacking) {
60  View v1;
61  View* v11 = new View;
62  View* v12 = new View;
63  View* v13 = new View;
64  v1.AddChild(v11);
65  v1.AddChild(v12);
66  v1.AddChild(v13);
67
68  // Order: v11, v12, v13
69  EXPECT_EQ(3U, v1.children().size());
70  EXPECT_EQ(v11, v1.children().front());
71  EXPECT_EQ(v13, v1.children().back());
72
73  // Move v11 to front.
74  // Resulting order: v12, v13, v11
75  v1.StackChildAtTop(v11);
76  EXPECT_EQ(v12, v1.children().front());
77  EXPECT_EQ(v11, v1.children().back());
78
79  // Move v11 to back.
80  // Resulting order: v11, v12, v13
81  v1.StackChildAtBottom(v11);
82  EXPECT_EQ(v11, v1.children().front());
83  EXPECT_EQ(v13, v1.children().back());
84
85  // Move v11 above v12.
86  // Resulting order: v12. v11, v13
87  v1.StackChildAbove(v11, v12);
88  EXPECT_EQ(v12, v1.children().front());
89  EXPECT_EQ(v13, v1.children().back());
90
91  // Move v11 below v12.
92  // Resulting order: v11, v12, v13
93  v1.StackChildBelow(v11, v12);
94  EXPECT_EQ(v11, v1.children().front());
95  EXPECT_EQ(v13, v1.children().back());
96}
97
98TEST_F(ViewTest, Layer) {
99  View v1;
100  v1.CreateLayer(ui::LAYER_NOT_DRAWN);
101  EXPECT_TRUE(v1.HasLayer());
102  v1.DestroyLayer();
103  EXPECT_FALSE(v1.HasLayer());
104
105  v1.CreateLayer(ui::LAYER_NOT_DRAWN);
106  scoped_ptr<ui::Layer>(v1.AcquireLayer());
107  // Acquiring the layer transfers ownership to the scoped_ptr above, so this
108  // test passes if it doesn't crash.
109}
110
111// ViewObserver ----------------------------------------------------------------
112
113typedef testing::Test ViewObserverTest;
114
115bool TreeChangeParamsMatch(const ViewObserver::TreeChangeParams& lhs,
116                           const ViewObserver::TreeChangeParams& rhs) {
117  return lhs.target == rhs.target &&  lhs.old_parent == rhs.old_parent &&
118      lhs.new_parent == rhs.new_parent && lhs.receiver == rhs.receiver &&
119      lhs.phase == rhs.phase;
120}
121
122class TreeChangeObserver : public ViewObserver {
123 public:
124  explicit TreeChangeObserver(View* observee) : observee_(observee) {
125    observee_->AddObserver(this);
126  }
127  virtual ~TreeChangeObserver() {
128    observee_->RemoveObserver(this);
129  }
130
131  void Reset() {
132      received_params_.clear();
133  }
134
135  const std::vector<TreeChangeParams>& received_params() {
136    return received_params_;
137  }
138
139 private:
140  // Overridden from ViewObserver:
141  virtual void OnViewTreeChange(const TreeChangeParams& params) OVERRIDE {
142    received_params_.push_back(params);
143  }
144
145  View* observee_;
146  std::vector<TreeChangeParams> received_params_;
147
148  DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver);
149};
150
151// Adds/Removes v11 to v1.
152TEST_F(ViewObserverTest, TreeChange_SimpleAddRemove) {
153  View v1;
154  TreeChangeObserver o1(&v1);
155  EXPECT_TRUE(o1.received_params().empty());
156
157  View v11;
158  v11.set_owned_by_parent(false);
159  TreeChangeObserver o11(&v11);
160  EXPECT_TRUE(o11.received_params().empty());
161
162  // Add.
163
164  v1.AddChild(&v11);
165
166  EXPECT_EQ(1U, o1.received_params().size());
167  ViewObserver::TreeChangeParams p1;
168  p1.target = &v11;
169  p1.receiver = &v1;
170  p1.old_parent = NULL;
171  p1.new_parent = &v1;
172  p1.phase = ViewObserver::DISPOSITION_CHANGED;
173  EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
174
175  EXPECT_EQ(2U, o11.received_params().size());
176  ViewObserver::TreeChangeParams p11 = p1;
177  p11.receiver = &v11;
178  p11.phase = ViewObserver::DISPOSITION_CHANGING;
179  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
180  p11.phase = ViewObserver::DISPOSITION_CHANGED;
181  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
182
183  o1.Reset();
184  o11.Reset();
185  EXPECT_TRUE(o1.received_params().empty());
186  EXPECT_TRUE(o11.received_params().empty());
187
188  // Remove.
189
190  v1.RemoveChild(&v11);
191
192  EXPECT_EQ(1U, o1.received_params().size());
193  p1.target = &v11;
194  p1.receiver = &v1;
195  p1.old_parent = &v1;
196  p1.new_parent = NULL;
197  p1.phase = ViewObserver::DISPOSITION_CHANGING;
198  EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
199
200  EXPECT_EQ(2U, o11.received_params().size());
201  p11 = p1;
202  p11.receiver = &v11;
203  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
204  p11.phase = ViewObserver::DISPOSITION_CHANGED;
205  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
206}
207
208// Creates these two trees:
209// v1
210//  +- v11
211// v111
212//  +- v1111
213//  +- v1112
214// Then adds/removes v111 from v11.
215TEST_F(ViewObserverTest, TreeChange_NestedAddRemove) {
216  View v1, v11, v111, v1111, v1112;
217
218  // Root tree.
219  v11.set_owned_by_parent(false);
220  v1.AddChild(&v11);
221
222  // Tree to be attached.
223  v111.set_owned_by_parent(false);
224  v1111.set_owned_by_parent(false);
225  v111.AddChild(&v1111);
226  v1112.set_owned_by_parent(false);
227  v111.AddChild(&v1112);
228
229  TreeChangeObserver o1(&v1), o11(&v11), o111(&v111), o1111(&v1111),
230      o1112(&v1112);
231  ViewObserver::TreeChangeParams p1, p11, p111, p1111, p1112;
232
233  // Add.
234
235  v11.AddChild(&v111);
236
237  EXPECT_EQ(1U, o1.received_params().size());
238  p1.target = &v111;
239  p1.receiver = &v1;
240  p1.old_parent = NULL;
241  p1.new_parent = &v11;
242  p1.phase = ViewObserver::DISPOSITION_CHANGED;
243  EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
244
245  EXPECT_EQ(1U, o11.received_params().size());
246  p11 = p1;
247  p11.receiver = &v11;
248  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
249
250  EXPECT_EQ(2U, o111.received_params().size());
251  p111 = p11;
252  p111.receiver = &v111;
253  p111.phase = ViewObserver::DISPOSITION_CHANGING;
254  EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
255  p111.phase = ViewObserver::DISPOSITION_CHANGED;
256  EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
257
258  EXPECT_EQ(2U, o1111.received_params().size());
259  p1111 = p111;
260  p1111.receiver = &v1111;
261  p1111.phase = ViewObserver::DISPOSITION_CHANGING;
262  EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front()));
263  p1111.phase = ViewObserver::DISPOSITION_CHANGED;
264  EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back()));
265
266  EXPECT_EQ(2U, o1112.received_params().size());
267  p1112 = p111;
268  p1112.receiver = &v1112;
269  p1112.phase = ViewObserver::DISPOSITION_CHANGING;
270  EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front()));
271  p1112.phase = ViewObserver::DISPOSITION_CHANGED;
272  EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back()));
273
274  // Remove.
275  o1.Reset();
276  o11.Reset();
277  o111.Reset();
278  o1111.Reset();
279  o1112.Reset();
280  EXPECT_TRUE(o1.received_params().empty());
281  EXPECT_TRUE(o11.received_params().empty());
282  EXPECT_TRUE(o111.received_params().empty());
283  EXPECT_TRUE(o1111.received_params().empty());
284  EXPECT_TRUE(o1112.received_params().empty());
285
286  v11.RemoveChild(&v111);
287
288  EXPECT_EQ(1U, o1.received_params().size());
289  p1.target = &v111;
290  p1.receiver = &v1;
291  p1.old_parent = &v11;
292  p1.new_parent = NULL;
293  p1.phase = ViewObserver::DISPOSITION_CHANGING;
294  EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
295
296  EXPECT_EQ(1U, o11.received_params().size());
297  p11 = p1;
298  p11.receiver = &v11;
299  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
300
301  EXPECT_EQ(2U, o111.received_params().size());
302  p111 = p11;
303  p111.receiver = &v111;
304  p111.phase = ViewObserver::DISPOSITION_CHANGING;
305  EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
306  p111.phase = ViewObserver::DISPOSITION_CHANGED;
307  EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
308
309  EXPECT_EQ(2U, o1111.received_params().size());
310  p1111 = p111;
311  p1111.receiver = &v1111;
312  p1111.phase = ViewObserver::DISPOSITION_CHANGING;
313  EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front()));
314  p1111.phase = ViewObserver::DISPOSITION_CHANGED;
315  EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back()));
316
317  EXPECT_EQ(2U, o1112.received_params().size());
318  p1112 = p111;
319  p1112.receiver = &v1112;
320  p1112.phase = ViewObserver::DISPOSITION_CHANGING;
321  EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front()));
322  p1112.phase = ViewObserver::DISPOSITION_CHANGED;
323  EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back()));
324}
325
326TEST_F(ViewObserverTest, TreeChange_Reparent) {
327  View v1, v11, v12, v111;
328  v11.set_owned_by_parent(false);
329  v111.set_owned_by_parent(false);
330  v12.set_owned_by_parent(false);
331  v1.AddChild(&v11);
332  v1.AddChild(&v12);
333  v11.AddChild(&v111);
334
335  TreeChangeObserver o1(&v1), o11(&v11), o12(&v12), o111(&v111);
336
337  // Reparent.
338  v12.AddChild(&v111);
339
340  // v1 (root) should see both changing and changed notifications.
341  EXPECT_EQ(2U, o1.received_params().size());
342  ViewObserver::TreeChangeParams p1;
343  p1.target = &v111;
344  p1.receiver = &v1;
345  p1.old_parent = &v11;
346  p1.new_parent = &v12;
347  p1.phase = ViewObserver::DISPOSITION_CHANGING;
348  EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
349  p1.phase = ViewObserver::DISPOSITION_CHANGED;
350  EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
351
352  // v11 should see changing notifications.
353  EXPECT_EQ(1U, o11.received_params().size());
354  ViewObserver::TreeChangeParams p11;
355  p11 = p1;
356  p11.receiver = &v11;
357  p11.phase = ViewObserver::DISPOSITION_CHANGING;
358  EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
359
360  // v12 should see changed notifications.
361  EXPECT_EQ(1U, o12.received_params().size());
362  ViewObserver::TreeChangeParams p12;
363  p12 = p1;
364  p12.receiver = &v12;
365  p12.phase = ViewObserver::DISPOSITION_CHANGED;
366  EXPECT_TRUE(TreeChangeParamsMatch(p12, o12.received_params().back()));
367
368  // v111 should see both changing and changed notifications.
369  EXPECT_EQ(2U, o111.received_params().size());
370  ViewObserver::TreeChangeParams p111;
371  p111 = p1;
372  p111.receiver = &v111;
373  p111.phase = ViewObserver::DISPOSITION_CHANGING;
374  EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
375  p111.phase = ViewObserver::DISPOSITION_CHANGED;
376  EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
377}
378
379class VisibilityObserver : public ViewObserver {
380 public:
381  typedef std::pair<ViewObserver::DispositionChangePhase, bool> LogEntry;
382  typedef std::vector<LogEntry> LogEntries;
383
384  VisibilityObserver(View* view) : view_(view) {
385    view_->AddObserver(this);
386  }
387  virtual ~VisibilityObserver() {
388    view_->RemoveObserver(this);
389  }
390
391  const LogEntries& log_entries() const { return log_entries_; }
392
393 private:
394  // Overridden from ViewObserver:
395  virtual void OnViewVisibilityChange(
396      View* view,
397      ViewObserver::DispositionChangePhase phase) OVERRIDE {
398    DCHECK_EQ(view_, view);
399    log_entries_.push_back(std::make_pair(phase, view->visible()));
400  }
401
402  View* view_;
403  LogEntries log_entries_;
404
405  DISALLOW_COPY_AND_ASSIGN(VisibilityObserver);
406};
407
408TEST_F(ViewObserverTest, VisibilityChange) {
409  View v1;  // Starts out visible.
410
411  VisibilityObserver o1(&v1);
412
413  v1.SetVisible(false);
414
415  EXPECT_EQ(2U, o1.log_entries().size());
416  EXPECT_EQ(ViewObserver::DISPOSITION_CHANGING, o1.log_entries().front().first);
417  EXPECT_EQ(o1.log_entries().front().second, true);
418  EXPECT_EQ(ViewObserver::DISPOSITION_CHANGED, o1.log_entries().back().first);
419  EXPECT_EQ(o1.log_entries().back().second, false);
420}
421
422class BoundsObserver : public ViewObserver {
423 public:
424  typedef std::pair<gfx::Rect, gfx::Rect> BoundsChange;
425  typedef std::vector<BoundsChange> BoundsChanges;
426
427  explicit BoundsObserver(View* view) : view_(view) {
428    view_->AddObserver(this);
429  }
430  virtual ~BoundsObserver() {
431    view_->RemoveObserver(this);
432  }
433
434  const BoundsChanges& bounds_changes() const { return bounds_changes_; }
435
436 private:
437  virtual void OnViewBoundsChanged(View* view,
438                                  const gfx::Rect& old_bounds,
439                                  const gfx::Rect& new_bounds) OVERRIDE {
440    DCHECK_EQ(view_, view);
441    bounds_changes_.push_back(std::make_pair(old_bounds, new_bounds));
442  }
443
444  View* view_;
445  BoundsChanges bounds_changes_;
446
447  DISALLOW_COPY_AND_ASSIGN(BoundsObserver);
448};
449
450TEST_F(ViewObserverTest, BoundsChanged) {
451  View v1;
452  BoundsObserver o1(&v1);
453
454  gfx::Rect new_bounds(0, 0, 10, 10);
455
456  v1.SetBounds(new_bounds);
457  EXPECT_EQ(1U, o1.bounds_changes().size());
458  EXPECT_EQ(gfx::Rect(), o1.bounds_changes().front().first);
459  EXPECT_EQ(new_bounds, o1.bounds_changes().front().second);
460}
461
462}  // namespace v2
463