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",