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 "components/mus/public/cpp/view.h"
7 #include "base/logging.h"
8 #include "base/strings/stringprintf.h"
9 #include "components/mus/public/cpp/lib/view_private.h"
10 #include "components/mus/public/cpp/util.h"
11 #include "components/mus/public/cpp/view_observer.h"
12 #include "components/mus/public/cpp/view_property.h"
13 #include "testing/gtest/include/gtest/gtest.h"
17 // View ------------------------------------------------------------------------
19 typedef testing::Test ViewTest
;
21 // Subclass with public ctor/dtor.
22 class TestView
: public View
{
24 TestView() { ViewPrivate(this).set_id(1); }
28 MOJO_DISALLOW_COPY_AND_ASSIGN(TestView
);
31 TEST_F(ViewTest
, AddChild
) {
35 EXPECT_EQ(1U, v1
.children().size());
38 TEST_F(ViewTest
, RemoveChild
) {
42 EXPECT_EQ(1U, v1
.children().size());
44 EXPECT_EQ(0U, v1
.children().size());
47 TEST_F(ViewTest
, Reparent
) {
52 EXPECT_EQ(1U, v1
.children().size());
54 EXPECT_EQ(1U, v2
.children().size());
55 EXPECT_EQ(0U, v1
.children().size());
58 TEST_F(ViewTest
, Contains
) {
64 EXPECT_TRUE(v1
.Contains(&v11
));
66 // Indirect descendant.
69 EXPECT_TRUE(v1
.Contains(&v111
));
72 TEST_F(ViewTest
, GetChildById
) {
74 ViewPrivate(&v1
).set_id(1);
76 ViewPrivate(&v11
).set_id(11);
79 ViewPrivate(&v111
).set_id(111);
82 // Find direct & indirect descendents.
83 EXPECT_EQ(&v11
, v1
.GetChildById(v11
.id()));
84 EXPECT_EQ(&v111
, v1
.GetChildById(v111
.id()));
87 TEST_F(ViewTest
, DrawnAndVisible
) {
89 EXPECT_TRUE(v1
.visible());
90 EXPECT_FALSE(v1
.IsDrawn());
92 ViewPrivate(&v1
).set_drawn(true);
96 EXPECT_TRUE(v11
.visible());
97 EXPECT_TRUE(v11
.IsDrawn());
100 EXPECT_TRUE(v11
.visible());
101 EXPECT_FALSE(v11
.IsDrawn());
105 DEFINE_VIEW_PROPERTY_KEY(int, kIntKey
, -2);
106 DEFINE_VIEW_PROPERTY_KEY(const char*, kStringKey
, "squeamish");
109 TEST_F(ViewTest
, Property
) {
112 // Non-existent properties should return the default values.
113 EXPECT_EQ(-2, v
.GetLocalProperty(kIntKey
));
114 EXPECT_EQ(std::string("squeamish"), v
.GetLocalProperty(kStringKey
));
116 // A set property value should be returned again (even if it's the default
118 v
.SetLocalProperty(kIntKey
, INT_MAX
);
119 EXPECT_EQ(INT_MAX
, v
.GetLocalProperty(kIntKey
));
120 v
.SetLocalProperty(kIntKey
, -2);
121 EXPECT_EQ(-2, v
.GetLocalProperty(kIntKey
));
122 v
.SetLocalProperty(kIntKey
, INT_MIN
);
123 EXPECT_EQ(INT_MIN
, v
.GetLocalProperty(kIntKey
));
125 v
.SetLocalProperty(kStringKey
, static_cast<const char*>(NULL
));
126 EXPECT_EQ(NULL
, v
.GetLocalProperty(kStringKey
));
127 v
.SetLocalProperty(kStringKey
, "squeamish");
128 EXPECT_EQ(std::string("squeamish"), v
.GetLocalProperty(kStringKey
));
129 v
.SetLocalProperty(kStringKey
, "ossifrage");
130 EXPECT_EQ(std::string("ossifrage"), v
.GetLocalProperty(kStringKey
));
132 // ClearProperty should restore the default value.
133 v
.ClearLocalProperty(kIntKey
);
134 EXPECT_EQ(-2, v
.GetLocalProperty(kIntKey
));
135 v
.ClearLocalProperty(kStringKey
);
136 EXPECT_EQ(std::string("squeamish"), v
.GetLocalProperty(kStringKey
));
144 virtual ~TestProperty() { last_deleted_
= this; }
145 static TestProperty
* last_deleted() { return last_deleted_
; }
148 static TestProperty
* last_deleted_
;
149 MOJO_DISALLOW_COPY_AND_ASSIGN(TestProperty
);
152 TestProperty
* TestProperty::last_deleted_
= NULL
;
154 DEFINE_OWNED_VIEW_PROPERTY_KEY(TestProperty
, kOwnedKey
, NULL
);
158 TEST_F(ViewTest
, OwnedProperty
) {
159 TestProperty
* p3
= NULL
;
162 EXPECT_EQ(NULL
, v
.GetLocalProperty(kOwnedKey
));
163 TestProperty
* p1
= new TestProperty();
164 v
.SetLocalProperty(kOwnedKey
, p1
);
165 EXPECT_EQ(p1
, v
.GetLocalProperty(kOwnedKey
));
166 EXPECT_EQ(NULL
, TestProperty::last_deleted());
168 TestProperty
* p2
= new TestProperty();
169 v
.SetLocalProperty(kOwnedKey
, p2
);
170 EXPECT_EQ(p2
, v
.GetLocalProperty(kOwnedKey
));
171 EXPECT_EQ(p1
, TestProperty::last_deleted());
173 v
.ClearLocalProperty(kOwnedKey
);
174 EXPECT_EQ(NULL
, v
.GetLocalProperty(kOwnedKey
));
175 EXPECT_EQ(p2
, TestProperty::last_deleted());
177 p3
= new TestProperty();
178 v
.SetLocalProperty(kOwnedKey
, p3
);
179 EXPECT_EQ(p3
, v
.GetLocalProperty(kOwnedKey
));
180 EXPECT_EQ(p2
, TestProperty::last_deleted());
183 EXPECT_EQ(p3
, TestProperty::last_deleted());
186 // ViewObserver --------------------------------------------------------
188 typedef testing::Test ViewObserverTest
;
190 bool TreeChangeParamsMatch(const ViewObserver::TreeChangeParams
& lhs
,
191 const ViewObserver::TreeChangeParams
& rhs
) {
192 return lhs
.target
== rhs
.target
&& lhs
.old_parent
== rhs
.old_parent
&&
193 lhs
.new_parent
== rhs
.new_parent
&& lhs
.receiver
== rhs
.receiver
;
196 class TreeChangeObserver
: public ViewObserver
{
198 explicit TreeChangeObserver(View
* observee
) : observee_(observee
) {
199 observee_
->AddObserver(this);
201 ~TreeChangeObserver() override
{ observee_
->RemoveObserver(this); }
203 void Reset() { received_params_
.clear(); }
205 const std::vector
<TreeChangeParams
>& received_params() {
206 return received_params_
;
210 // Overridden from ViewObserver:
211 void OnTreeChanging(const TreeChangeParams
& params
) override
{
212 received_params_
.push_back(params
);
214 void OnTreeChanged(const TreeChangeParams
& params
) override
{
215 received_params_
.push_back(params
);
219 std::vector
<TreeChangeParams
> received_params_
;
221 MOJO_DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver
);
224 // Adds/Removes v11 to v1.
225 TEST_F(ViewObserverTest
, TreeChange_SimpleAddRemove
) {
227 TreeChangeObserver
o1(&v1
);
228 EXPECT_TRUE(o1
.received_params().empty());
231 TreeChangeObserver
o11(&v11
);
232 EXPECT_TRUE(o11
.received_params().empty());
238 EXPECT_EQ(2U, o1
.received_params().size());
239 ViewObserver::TreeChangeParams p1
;
242 p1
.old_parent
= NULL
;
244 EXPECT_TRUE(TreeChangeParamsMatch(p1
, o1
.received_params().back()));
246 EXPECT_EQ(2U, o11
.received_params().size());
247 ViewObserver::TreeChangeParams p11
= p1
;
249 EXPECT_TRUE(TreeChangeParamsMatch(p11
, o11
.received_params().front()));
250 EXPECT_TRUE(TreeChangeParamsMatch(p11
, o11
.received_params().back()));
254 EXPECT_TRUE(o1
.received_params().empty());
255 EXPECT_TRUE(o11
.received_params().empty());
259 v1
.RemoveChild(&v11
);
261 EXPECT_EQ(2U, o1
.received_params().size());
265 p1
.new_parent
= NULL
;
266 EXPECT_TRUE(TreeChangeParamsMatch(p1
, o1
.received_params().front()));
268 EXPECT_EQ(2U, o11
.received_params().size());
271 EXPECT_TRUE(TreeChangeParamsMatch(p11
, o11
.received_params().front()));
272 EXPECT_TRUE(TreeChangeParamsMatch(p11
, o11
.received_params().back()));
275 // Creates these two trees:
281 // Then adds/removes v111 from v11.
282 TEST_F(ViewObserverTest
, TreeChange_NestedAddRemove
) {
283 TestView v1
, v11
, v111
, v1111
, v1112
;
288 // Tree to be attached.
289 v111
.AddChild(&v1111
);
290 v111
.AddChild(&v1112
);
292 TreeChangeObserver
o1(&v1
), o11(&v11
), o111(&v111
), o1111(&v1111
),
294 ViewObserver::TreeChangeParams p1
, p11
, p111
, p1111
, p1112
;
300 EXPECT_EQ(2U, o1
.received_params().size());
303 p1
.old_parent
= NULL
;
304 p1
.new_parent
= &v11
;
305 EXPECT_TRUE(TreeChangeParamsMatch(p1
, o1
.received_params().back()));
307 EXPECT_EQ(2U, o11
.received_params().size());
310 EXPECT_TRUE(TreeChangeParamsMatch(p11
, o11
.received_params().back()));
312 EXPECT_EQ(2U, o111
.received_params().size());
314 p111
.receiver
= &v111
;
315 EXPECT_TRUE(TreeChangeParamsMatch(p111
, o111
.received_params().front()));
316 EXPECT_TRUE(TreeChangeParamsMatch(p111
, o111
.received_params().back()));
318 EXPECT_EQ(2U, o1111
.received_params().size());
320 p1111
.receiver
= &v1111
;
321 EXPECT_TRUE(TreeChangeParamsMatch(p1111
, o1111
.received_params().front()));
322 EXPECT_TRUE(TreeChangeParamsMatch(p1111
, o1111
.received_params().back()));
324 EXPECT_EQ(2U, o1112
.received_params().size());
326 p1112
.receiver
= &v1112
;
327 EXPECT_TRUE(TreeChangeParamsMatch(p1112
, o1112
.received_params().front()));
328 EXPECT_TRUE(TreeChangeParamsMatch(p1112
, o1112
.received_params().back()));
336 EXPECT_TRUE(o1
.received_params().empty());
337 EXPECT_TRUE(o11
.received_params().empty());
338 EXPECT_TRUE(o111
.received_params().empty());
339 EXPECT_TRUE(o1111
.received_params().empty());
340 EXPECT_TRUE(o1112
.received_params().empty());
342 v11
.RemoveChild(&v111
);
344 EXPECT_EQ(2U, o1
.received_params().size());
347 p1
.old_parent
= &v11
;
348 p1
.new_parent
= NULL
;
349 EXPECT_TRUE(TreeChangeParamsMatch(p1
, o1
.received_params().front()));
351 EXPECT_EQ(2U, o11
.received_params().size());
354 EXPECT_TRUE(TreeChangeParamsMatch(p11
, o11
.received_params().front()));
356 EXPECT_EQ(2U, o111
.received_params().size());
358 p111
.receiver
= &v111
;
359 EXPECT_TRUE(TreeChangeParamsMatch(p111
, o111
.received_params().front()));
360 EXPECT_TRUE(TreeChangeParamsMatch(p111
, o111
.received_params().back()));
362 EXPECT_EQ(2U, o1111
.received_params().size());
364 p1111
.receiver
= &v1111
;
365 EXPECT_TRUE(TreeChangeParamsMatch(p1111
, o1111
.received_params().front()));
366 EXPECT_TRUE(TreeChangeParamsMatch(p1111
, o1111
.received_params().back()));
368 EXPECT_EQ(2U, o1112
.received_params().size());
370 p1112
.receiver
= &v1112
;
371 EXPECT_TRUE(TreeChangeParamsMatch(p1112
, o1112
.received_params().front()));
372 EXPECT_TRUE(TreeChangeParamsMatch(p1112
, o1112
.received_params().back()));
375 TEST_F(ViewObserverTest
, TreeChange_Reparent
) {
376 TestView v1
, v11
, v12
, v111
;
381 TreeChangeObserver
o1(&v1
), o11(&v11
), o12(&v12
), o111(&v111
);
386 // v1 (root) should see both changing and changed notifications.
387 EXPECT_EQ(4U, o1
.received_params().size());
388 ViewObserver::TreeChangeParams p1
;
391 p1
.old_parent
= &v11
;
392 p1
.new_parent
= &v12
;
393 EXPECT_TRUE(TreeChangeParamsMatch(p1
, o1
.received_params().front()));
394 EXPECT_TRUE(TreeChangeParamsMatch(p1
, o1
.received_params().back()));
396 // v11 should see changing notifications.
397 EXPECT_EQ(2U, o11
.received_params().size());
398 ViewObserver::TreeChangeParams p11
;
401 EXPECT_TRUE(TreeChangeParamsMatch(p11
, o11
.received_params().front()));
403 // v12 should see changed notifications.
404 EXPECT_EQ(2U, o12
.received_params().size());
405 ViewObserver::TreeChangeParams p12
;
408 EXPECT_TRUE(TreeChangeParamsMatch(p12
, o12
.received_params().back()));
410 // v111 should see both changing and changed notifications.
411 EXPECT_EQ(2U, o111
.received_params().size());
412 ViewObserver::TreeChangeParams p111
;
414 p111
.receiver
= &v111
;
415 EXPECT_TRUE(TreeChangeParamsMatch(p111
, o111
.received_params().front()));
416 EXPECT_TRUE(TreeChangeParamsMatch(p111
, o111
.received_params().back()));
421 class OrderChangeObserver
: public ViewObserver
{
426 mojo::OrderDirection direction
;
428 typedef std::vector
<Change
> Changes
;
430 explicit OrderChangeObserver(View
* observee
) : observee_(observee
) {
431 observee_
->AddObserver(this);
433 ~OrderChangeObserver() override
{ observee_
->RemoveObserver(this); }
435 Changes
GetAndClearChanges() {
437 changes_
.swap(changes
);
442 // Overridden from ViewObserver:
443 void OnViewReordering(View
* view
,
445 mojo::OrderDirection direction
) override
{
446 OnViewReordered(view
, relative_view
, direction
);
449 void OnViewReordered(View
* view
,
451 mojo::OrderDirection direction
) override
{
454 change
.relative_view
= relative_view
;
455 change
.direction
= direction
;
456 changes_
.push_back(change
);
462 MOJO_DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver
);
467 TEST_F(ViewObserverTest
, Order
) {
468 TestView v1
, v11
, v12
, v13
;
473 // Order: v11, v12, v13
474 EXPECT_EQ(3U, v1
.children().size());
475 EXPECT_EQ(&v11
, v1
.children().front());
476 EXPECT_EQ(&v13
, v1
.children().back());
479 OrderChangeObserver
observer(&v11
);
481 // Move v11 to front.
482 // Resulting order: v12, v13, v11
484 EXPECT_EQ(&v12
, v1
.children().front());
485 EXPECT_EQ(&v11
, v1
.children().back());
487 OrderChangeObserver::Changes changes
= observer
.GetAndClearChanges();
488 ASSERT_EQ(2U, changes
.size());
489 EXPECT_EQ(&v11
, changes
[0].view
);
490 EXPECT_EQ(&v13
, changes
[0].relative_view
);
491 EXPECT_EQ(mojo::ORDER_DIRECTION_ABOVE
, changes
[0].direction
);
493 EXPECT_EQ(&v11
, changes
[1].view
);
494 EXPECT_EQ(&v13
, changes
[1].relative_view
);
495 EXPECT_EQ(mojo::ORDER_DIRECTION_ABOVE
, changes
[1].direction
);
499 OrderChangeObserver
observer(&v11
);
502 // Resulting order: v11, v12, v13
504 EXPECT_EQ(&v11
, v1
.children().front());
505 EXPECT_EQ(&v13
, v1
.children().back());
507 OrderChangeObserver::Changes changes
= observer
.GetAndClearChanges();
508 ASSERT_EQ(2U, changes
.size());
509 EXPECT_EQ(&v11
, changes
[0].view
);
510 EXPECT_EQ(&v12
, changes
[0].relative_view
);
511 EXPECT_EQ(mojo::ORDER_DIRECTION_BELOW
, changes
[0].direction
);
513 EXPECT_EQ(&v11
, changes
[1].view
);
514 EXPECT_EQ(&v12
, changes
[1].relative_view
);
515 EXPECT_EQ(mojo::ORDER_DIRECTION_BELOW
, changes
[1].direction
);
519 OrderChangeObserver
observer(&v11
);
521 // Move v11 above v12.
522 // Resulting order: v12. v11, v13
523 v11
.Reorder(&v12
, mojo::ORDER_DIRECTION_ABOVE
);
524 EXPECT_EQ(&v12
, v1
.children().front());
525 EXPECT_EQ(&v13
, v1
.children().back());
527 OrderChangeObserver::Changes changes
= observer
.GetAndClearChanges();
528 ASSERT_EQ(2U, changes
.size());
529 EXPECT_EQ(&v11
, changes
[0].view
);
530 EXPECT_EQ(&v12
, changes
[0].relative_view
);
531 EXPECT_EQ(mojo::ORDER_DIRECTION_ABOVE
, changes
[0].direction
);
533 EXPECT_EQ(&v11
, changes
[1].view
);
534 EXPECT_EQ(&v12
, changes
[1].relative_view
);
535 EXPECT_EQ(mojo::ORDER_DIRECTION_ABOVE
, changes
[1].direction
);
539 OrderChangeObserver
observer(&v11
);
541 // Move v11 below v12.
542 // Resulting order: v11, v12, v13
543 v11
.Reorder(&v12
, mojo::ORDER_DIRECTION_BELOW
);
544 EXPECT_EQ(&v11
, v1
.children().front());
545 EXPECT_EQ(&v13
, v1
.children().back());
547 OrderChangeObserver::Changes changes
= observer
.GetAndClearChanges();
548 ASSERT_EQ(2U, changes
.size());
549 EXPECT_EQ(&v11
, changes
[0].view
);
550 EXPECT_EQ(&v12
, changes
[0].relative_view
);
551 EXPECT_EQ(mojo::ORDER_DIRECTION_BELOW
, changes
[0].direction
);
553 EXPECT_EQ(&v11
, changes
[1].view
);
554 EXPECT_EQ(&v12
, changes
[1].relative_view
);
555 EXPECT_EQ(mojo::ORDER_DIRECTION_BELOW
, changes
[1].direction
);
561 typedef std::vector
<std::string
> Changes
;
563 std::string
ViewIdToString(Id id
) {
564 return (id
== 0) ? "null"
565 : base::StringPrintf("%d,%d", HiWord(id
), LoWord(id
));
568 std::string
RectToString(const mojo::Rect
& rect
) {
569 return base::StringPrintf("%d,%d %dx%d", rect
.x
, rect
.y
, rect
.width
,
573 class BoundsChangeObserver
: public ViewObserver
{
575 explicit BoundsChangeObserver(View
* view
) : view_(view
) {
576 view_
->AddObserver(this);
578 ~BoundsChangeObserver() override
{ view_
->RemoveObserver(this); }
580 Changes
GetAndClearChanges() {
582 changes
.swap(changes_
);
587 // Overridden from ViewObserver:
588 void OnViewBoundsChanging(View
* view
,
589 const mojo::Rect
& old_bounds
,
590 const mojo::Rect
& new_bounds
) override
{
591 changes_
.push_back(base::StringPrintf(
592 "view=%s old_bounds=%s new_bounds=%s phase=changing",
593 ViewIdToString(view
->id()).c_str(), RectToString(old_bounds
).c_str(),
594 RectToString(new_bounds
).c_str()));
596 void OnViewBoundsChanged(View
* view
,
597 const mojo::Rect
& old_bounds
,
598 const mojo::Rect
& new_bounds
) override
{
599 changes_
.push_back(base::StringPrintf(
600 "view=%s old_bounds=%s new_bounds=%s phase=changed",
601 ViewIdToString(view
->id()).c_str(), RectToString(old_bounds
).c_str(),
602 RectToString(new_bounds
).c_str()));
608 MOJO_DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver
);
613 TEST_F(ViewObserverTest
, SetBounds
) {
616 BoundsChangeObserver
observer(&v1
);
618 rect
.width
= rect
.height
= 100;
621 Changes changes
= observer
.GetAndClearChanges();
622 ASSERT_EQ(2U, changes
.size());
624 "view=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changing",
627 "view=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changed",
634 class VisibilityChangeObserver
: public ViewObserver
{
636 explicit VisibilityChangeObserver(View
* view
) : view_(view
) {
637 view_
->AddObserver(this);
639 ~VisibilityChangeObserver() override
{ view_
->RemoveObserver(this); }
641 Changes
GetAndClearChanges() {
643 changes
.swap(changes_
);
648 // Overridden from ViewObserver:
649 void OnViewVisibilityChanging(View
* view
) override
{
651 base::StringPrintf("view=%s phase=changing visibility=%s",
652 ViewIdToString(view
->id()).c_str(),
653 view
->visible() ? "true" : "false"));
655 void OnViewVisibilityChanged(View
* view
) override
{
656 changes_
.push_back(base::StringPrintf("view=%s phase=changed visibility=%s",
657 ViewIdToString(view
->id()).c_str(),
658 view
->visible() ? "true" : "false"));
664 MOJO_DISALLOW_COPY_AND_ASSIGN(VisibilityChangeObserver
);
669 TEST_F(ViewObserverTest
, SetVisible
) {
671 EXPECT_TRUE(v1
.visible());
673 // Change visibility from true to false and make sure we get notifications.
674 VisibilityChangeObserver
observer(&v1
);
675 v1
.SetVisible(false);
677 Changes changes
= observer
.GetAndClearChanges();
678 ASSERT_EQ(2U, changes
.size());
679 EXPECT_EQ("view=0,1 phase=changing visibility=true", changes
[0]);
680 EXPECT_EQ("view=0,1 phase=changed visibility=false", changes
[1]);
683 // Set visible to existing value and verify no notifications.
684 VisibilityChangeObserver
observer(&v1
);
685 v1
.SetVisible(false);
686 EXPECT_TRUE(observer
.GetAndClearChanges().empty());
690 TEST_F(ViewObserverTest
, SetVisibleParent
) {
692 ViewPrivate(&parent
).set_id(1);
694 ViewPrivate(&child
).set_id(2);
695 parent
.AddChild(&child
);
696 EXPECT_TRUE(parent
.visible());
697 EXPECT_TRUE(child
.visible());
699 // Change visibility from true to false and make sure we get notifications
701 VisibilityChangeObserver
observer(&parent
);
702 child
.SetVisible(false);
704 Changes changes
= observer
.GetAndClearChanges();
705 ASSERT_EQ(1U, changes
.size());
706 EXPECT_EQ("view=0,2 phase=changed visibility=false", changes
[0]);
710 TEST_F(ViewObserverTest
, SetVisibleChild
) {
712 ViewPrivate(&parent
).set_id(1);
714 ViewPrivate(&child
).set_id(2);
715 parent
.AddChild(&child
);
716 EXPECT_TRUE(parent
.visible());
717 EXPECT_TRUE(child
.visible());
719 // Change visibility from true to false and make sure we get notifications
721 VisibilityChangeObserver
observer(&child
);
722 parent
.SetVisible(false);
724 Changes changes
= observer
.GetAndClearChanges();
725 ASSERT_EQ(1U, changes
.size());
726 EXPECT_EQ("view=0,1 phase=changed visibility=false", changes
[0]);
732 class SharedPropertyChangeObserver
: public ViewObserver
{
734 explicit SharedPropertyChangeObserver(View
* view
) : view_(view
) {
735 view_
->AddObserver(this);
737 ~SharedPropertyChangeObserver() override
{ view_
->RemoveObserver(this); }
739 Changes
GetAndClearChanges() {
741 changes
.swap(changes_
);
746 // Overridden from ViewObserver:
747 void OnViewSharedPropertyChanged(
749 const std::string
& name
,
750 const std::vector
<uint8_t>* old_data
,
751 const std::vector
<uint8_t>* new_data
) override
{
752 changes_
.push_back(base::StringPrintf(
753 "view=%s shared property changed key=%s old_value=%s new_value=%s",
754 ViewIdToString(view
->id()).c_str(), name
.c_str(),
755 VectorToString(old_data
).c_str(), VectorToString(new_data
).c_str()));
758 std::string
VectorToString(const std::vector
<uint8_t>* data
) {
770 MOJO_DISALLOW_COPY_AND_ASSIGN(SharedPropertyChangeObserver
);
775 TEST_F(ViewObserverTest
, SetLocalProperty
) {
777 std::vector
<uint8_t> one(1, '1');
780 // Change visibility from true to false and make sure we get notifications.
781 SharedPropertyChangeObserver
observer(&v1
);
782 v1
.SetSharedProperty("one", &one
);
783 Changes changes
= observer
.GetAndClearChanges();
784 ASSERT_EQ(1U, changes
.size());
786 "view=0,1 shared property changed key=one old_value=NULL new_value=1",
788 EXPECT_EQ(1U, v1
.shared_properties().size());
791 // Set visible to existing value and verify no notifications.
792 SharedPropertyChangeObserver
observer(&v1
);
793 v1
.SetSharedProperty("one", &one
);
794 EXPECT_TRUE(observer
.GetAndClearChanges().empty());
795 EXPECT_EQ(1U, v1
.shared_properties().size());
798 // Set the value to NULL to delete it.
799 // Change visibility from true to false and make sure we get notifications.
800 SharedPropertyChangeObserver
observer(&v1
);
801 v1
.SetSharedProperty("one", NULL
);
802 Changes changes
= observer
.GetAndClearChanges();
803 ASSERT_EQ(1U, changes
.size());
805 "view=0,1 shared property changed key=one old_value=1 new_value=NULL",
807 EXPECT_EQ(0U, v1
.shared_properties().size());
810 // Setting a null property to null shouldn't update us.
811 SharedPropertyChangeObserver
observer(&v1
);
812 v1
.SetSharedProperty("one", NULL
);
813 EXPECT_TRUE(observer
.GetAndClearChanges().empty());
814 EXPECT_EQ(0U, v1
.shared_properties().size());
820 typedef std::pair
<const void*, intptr_t> PropertyChangeInfo
;
822 class LocalPropertyChangeObserver
: public ViewObserver
{
824 explicit LocalPropertyChangeObserver(View
* view
)
825 : view_(view
), property_key_(nullptr), old_property_value_(-1) {
826 view_
->AddObserver(this);
828 ~LocalPropertyChangeObserver() override
{ view_
->RemoveObserver(this); }
830 PropertyChangeInfo
PropertyChangeInfoAndClear() {
831 PropertyChangeInfo
result(property_key_
, old_property_value_
);
832 property_key_
= NULL
;
833 old_property_value_
= -3;
838 void OnViewLocalPropertyChanged(View
* window
,
840 intptr_t old
) override
{
842 old_property_value_
= old
;
846 const void* property_key_
;
847 intptr_t old_property_value_
;
849 MOJO_DISALLOW_COPY_AND_ASSIGN(LocalPropertyChangeObserver
);
854 TEST_F(ViewObserverTest
, LocalPropertyChanged
) {
856 LocalPropertyChangeObserver
o(&v1
);
858 static const ViewProperty
<int> prop
= {-2};
860 v1
.SetLocalProperty(&prop
, 1);
861 EXPECT_EQ(PropertyChangeInfo(&prop
, -2), o
.PropertyChangeInfoAndClear());
862 v1
.SetLocalProperty(&prop
, -2);
863 EXPECT_EQ(PropertyChangeInfo(&prop
, 1), o
.PropertyChangeInfoAndClear());
864 v1
.SetLocalProperty(&prop
, 3);
865 EXPECT_EQ(PropertyChangeInfo(&prop
, -2), o
.PropertyChangeInfoAndClear());
866 v1
.ClearLocalProperty(&prop
);
867 EXPECT_EQ(PropertyChangeInfo(&prop
, 3), o
.PropertyChangeInfoAndClear());
869 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
870 EXPECT_EQ(PropertyChangeInfo(reinterpret_cast<const void*>(NULL
), -3),
871 o
.PropertyChangeInfoAndClear());