1 // Copyright 2014 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.
5 #include "mojo/services/public/cpp/view_manager/view.h"
7 #include "base/logging.h"
8 #include "base/strings/stringprintf.h"
9 #include "mojo/services/public/cpp/view_manager/lib/view_private.h"
10 #include "mojo/services/public/cpp/view_manager/util.h"
11 #include "mojo/services/public/cpp/view_manager/view_observer.h"
12 #include "testing/gtest/include/gtest/gtest.h"
16 // View ------------------------------------------------------------------------
18 typedef testing::Test ViewTest;
20 // Subclass with public ctor/dtor.
21 class TestView : public View {
24 ViewPrivate(this).set_id(1);
29 DISALLOW_COPY_AND_ASSIGN(TestView);
32 TEST_F(ViewTest, AddChild) {
36 EXPECT_EQ(1U, v1.children().size());
39 TEST_F(ViewTest, RemoveChild) {
43 EXPECT_EQ(1U, v1.children().size());
45 EXPECT_EQ(0U, v1.children().size());
48 TEST_F(ViewTest, Reparent) {
53 EXPECT_EQ(1U, v1.children().size());
55 EXPECT_EQ(1U, v2.children().size());
56 EXPECT_EQ(0U, v1.children().size());
59 TEST_F(ViewTest, Contains) {
65 EXPECT_TRUE(v1.Contains(&v11));
67 // Indirect descendant.
70 EXPECT_TRUE(v1.Contains(&v111));
73 TEST_F(ViewTest, GetChildById) {
75 ViewPrivate(&v1).set_id(1);
77 ViewPrivate(&v11).set_id(11);
80 ViewPrivate(&v111).set_id(111);
83 // Find direct & indirect descendents.
84 EXPECT_EQ(&v11, v1.GetChildById(v11.id()));
85 EXPECT_EQ(&v111, v1.GetChildById(v111.id()));
88 // ViewObserver --------------------------------------------------------
90 typedef testing::Test ViewObserverTest;
92 bool TreeChangeParamsMatch(const ViewObserver::TreeChangeParams& lhs,
93 const ViewObserver::TreeChangeParams& rhs) {
94 return lhs.target == rhs.target && lhs.old_parent == rhs.old_parent &&
95 lhs.new_parent == rhs.new_parent && lhs.receiver == rhs.receiver;
98 class TreeChangeObserver : public ViewObserver {
100 explicit TreeChangeObserver(View* observee) : observee_(observee) {
101 observee_->AddObserver(this);
103 virtual ~TreeChangeObserver() {
104 observee_->RemoveObserver(this);
108 received_params_.clear();
111 const std::vector<TreeChangeParams>& received_params() {
112 return received_params_;
116 // Overridden from ViewObserver:
117 virtual void OnTreeChanging(const TreeChangeParams& params) OVERRIDE {
118 received_params_.push_back(params);
120 virtual void OnTreeChanged(const TreeChangeParams& params) OVERRIDE {
121 received_params_.push_back(params);
125 std::vector<TreeChangeParams> received_params_;
127 DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver);
130 // Adds/Removes v11 to v1.
131 TEST_F(ViewObserverTest, TreeChange_SimpleAddRemove) {
133 TreeChangeObserver o1(&v1);
134 EXPECT_TRUE(o1.received_params().empty());
137 TreeChangeObserver o11(&v11);
138 EXPECT_TRUE(o11.received_params().empty());
144 EXPECT_EQ(2U, o1.received_params().size());
145 ViewObserver::TreeChangeParams p1;
148 p1.old_parent = NULL;
150 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
152 EXPECT_EQ(2U, o11.received_params().size());
153 ViewObserver::TreeChangeParams p11 = p1;
155 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
156 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
160 EXPECT_TRUE(o1.received_params().empty());
161 EXPECT_TRUE(o11.received_params().empty());
165 v1.RemoveChild(&v11);
167 EXPECT_EQ(2U, o1.received_params().size());
171 p1.new_parent = NULL;
172 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
174 EXPECT_EQ(2U, o11.received_params().size());
177 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
178 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
181 // Creates these two trees:
187 // Then adds/removes v111 from v11.
188 TEST_F(ViewObserverTest, TreeChange_NestedAddRemove) {
189 TestView v1, v11, v111, v1111, v1112;
194 // Tree to be attached.
195 v111.AddChild(&v1111);
196 v111.AddChild(&v1112);
198 TreeChangeObserver o1(&v1), o11(&v11), o111(&v111), o1111(&v1111),
200 ViewObserver::TreeChangeParams p1, p11, p111, p1111, p1112;
206 EXPECT_EQ(2U, o1.received_params().size());
209 p1.old_parent = NULL;
210 p1.new_parent = &v11;
211 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
213 EXPECT_EQ(2U, o11.received_params().size());
216 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back()));
218 EXPECT_EQ(2U, o111.received_params().size());
220 p111.receiver = &v111;
221 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
222 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
224 EXPECT_EQ(2U, o1111.received_params().size());
226 p1111.receiver = &v1111;
227 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front()));
228 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back()));
230 EXPECT_EQ(2U, o1112.received_params().size());
232 p1112.receiver = &v1112;
233 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front()));
234 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back()));
242 EXPECT_TRUE(o1.received_params().empty());
243 EXPECT_TRUE(o11.received_params().empty());
244 EXPECT_TRUE(o111.received_params().empty());
245 EXPECT_TRUE(o1111.received_params().empty());
246 EXPECT_TRUE(o1112.received_params().empty());
248 v11.RemoveChild(&v111);
250 EXPECT_EQ(2U, o1.received_params().size());
253 p1.old_parent = &v11;
254 p1.new_parent = NULL;
255 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
257 EXPECT_EQ(2U, o11.received_params().size());
260 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
262 EXPECT_EQ(2U, o111.received_params().size());
264 p111.receiver = &v111;
265 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
266 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
268 EXPECT_EQ(2U, o1111.received_params().size());
270 p1111.receiver = &v1111;
271 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front()));
272 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back()));
274 EXPECT_EQ(2U, o1112.received_params().size());
276 p1112.receiver = &v1112;
277 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front()));
278 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back()));
281 TEST_F(ViewObserverTest, TreeChange_Reparent) {
282 TestView v1, v11, v12, v111;
287 TreeChangeObserver o1(&v1), o11(&v11), o12(&v12), o111(&v111);
292 // v1 (root) should see both changing and changed notifications.
293 EXPECT_EQ(4U, o1.received_params().size());
294 ViewObserver::TreeChangeParams p1;
297 p1.old_parent = &v11;
298 p1.new_parent = &v12;
299 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front()));
300 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back()));
302 // v11 should see changing notifications.
303 EXPECT_EQ(2U, o11.received_params().size());
304 ViewObserver::TreeChangeParams p11;
307 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front()));
309 // v12 should see changed notifications.
310 EXPECT_EQ(2U, o12.received_params().size());
311 ViewObserver::TreeChangeParams p12;
314 EXPECT_TRUE(TreeChangeParamsMatch(p12, o12.received_params().back()));
316 // v111 should see both changing and changed notifications.
317 EXPECT_EQ(2U, o111.received_params().size());
318 ViewObserver::TreeChangeParams p111;
320 p111.receiver = &v111;
321 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front()));
322 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back()));
327 class OrderChangeObserver : public ViewObserver {
332 OrderDirection direction;
334 typedef std::vector<Change> Changes;
336 explicit OrderChangeObserver(View* observee) : observee_(observee) {
337 observee_->AddObserver(this);
339 virtual ~OrderChangeObserver() {
340 observee_->RemoveObserver(this);
343 Changes GetAndClearChanges() {
345 changes_.swap(changes);
350 // Overridden from ViewObserver:
351 virtual void OnViewReordering(View* view,
353 OrderDirection direction) OVERRIDE {
354 OnViewReordered(view, relative_view, direction);
357 virtual void OnViewReordered(View* view,
359 OrderDirection direction) OVERRIDE {
362 change.relative_view = relative_view;
363 change.direction = direction;
364 changes_.push_back(change);
370 DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver);
375 TEST_F(ViewObserverTest, Order) {
376 TestView v1, v11, v12, v13;
381 // Order: v11, v12, v13
382 EXPECT_EQ(3U, v1.children().size());
383 EXPECT_EQ(&v11, v1.children().front());
384 EXPECT_EQ(&v13, v1.children().back());
387 OrderChangeObserver observer(&v11);
389 // Move v11 to front.
390 // Resulting order: v12, v13, v11
392 EXPECT_EQ(&v12, v1.children().front());
393 EXPECT_EQ(&v11, v1.children().back());
395 OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
396 EXPECT_EQ(2U, changes.size());
397 EXPECT_EQ(&v11, changes[0].view);
398 EXPECT_EQ(&v13, changes[0].relative_view);
399 EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[0].direction);
401 EXPECT_EQ(&v11, changes[1].view);
402 EXPECT_EQ(&v13, changes[1].relative_view);
403 EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[1].direction);
407 OrderChangeObserver observer(&v11);
410 // Resulting order: v11, v12, v13
412 EXPECT_EQ(&v11, v1.children().front());
413 EXPECT_EQ(&v13, v1.children().back());
415 OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
416 EXPECT_EQ(2U, changes.size());
417 EXPECT_EQ(&v11, changes[0].view);
418 EXPECT_EQ(&v12, changes[0].relative_view);
419 EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[0].direction);
421 EXPECT_EQ(&v11, changes[1].view);
422 EXPECT_EQ(&v12, changes[1].relative_view);
423 EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[1].direction);
427 OrderChangeObserver observer(&v11);
429 // Move v11 above v12.
430 // Resulting order: v12. v11, v13
431 v11.Reorder(&v12, ORDER_DIRECTION_ABOVE);
432 EXPECT_EQ(&v12, v1.children().front());
433 EXPECT_EQ(&v13, v1.children().back());
435 OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
436 EXPECT_EQ(2U, changes.size());
437 EXPECT_EQ(&v11, changes[0].view);
438 EXPECT_EQ(&v12, changes[0].relative_view);
439 EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[0].direction);
441 EXPECT_EQ(&v11, changes[1].view);
442 EXPECT_EQ(&v12, changes[1].relative_view);
443 EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[1].direction);
447 OrderChangeObserver observer(&v11);
449 // Move v11 below v12.
450 // Resulting order: v11, v12, v13
451 v11.Reorder(&v12, ORDER_DIRECTION_BELOW);
452 EXPECT_EQ(&v11, v1.children().front());
453 EXPECT_EQ(&v13, v1.children().back());
455 OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
456 EXPECT_EQ(2U, changes.size());
457 EXPECT_EQ(&v11, changes[0].view);
458 EXPECT_EQ(&v12, changes[0].relative_view);
459 EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[0].direction);
461 EXPECT_EQ(&v11, changes[1].view);
462 EXPECT_EQ(&v12, changes[1].relative_view);
463 EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[1].direction);
469 typedef std::vector<std::string> Changes;
471 std::string ViewIdToString(Id id) {
472 return (id == 0) ? "null" :
473 base::StringPrintf("%d,%d", HiWord(id), LoWord(id));
476 std::string RectToString(const gfx::Rect& rect) {
477 return base::StringPrintf("%d,%d %dx%d",
478 rect.x(), rect.y(), rect.width(), rect.height());
481 class BoundsChangeObserver : public ViewObserver {
483 explicit BoundsChangeObserver(View* view) : view_(view) {
484 view_->AddObserver(this);
486 virtual ~BoundsChangeObserver() {
487 view_->RemoveObserver(this);
490 Changes GetAndClearChanges() {
492 changes.swap(changes_);
497 // Overridden from ViewObserver:
498 virtual void OnViewBoundsChanging(View* view,
499 const gfx::Rect& old_bounds,
500 const gfx::Rect& new_bounds) OVERRIDE {
503 "view=%s old_bounds=%s new_bounds=%s phase=changing",
504 ViewIdToString(view->id()).c_str(),
505 RectToString(old_bounds).c_str(),
506 RectToString(new_bounds).c_str()));
508 virtual void OnViewBoundsChanged(View* view,
509 const gfx::Rect& old_bounds,
510 const gfx::Rect& new_bounds) OVERRIDE {
513 "view=%s old_bounds=%s new_bounds=%s phase=changed",
514 ViewIdToString(view->id()).c_str(),
515 RectToString(old_bounds).c_str(),
516 RectToString(new_bounds).c_str()));
522 DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver);
527 TEST_F(ViewObserverTest, SetBounds) {
530 BoundsChangeObserver observer(&v1);
531 v1.SetBounds(gfx::Rect(0, 0, 100, 100));
533 Changes changes = observer.GetAndClearChanges();
534 EXPECT_EQ(2U, changes.size());
536 "view=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changing",
539 "view=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changed",