OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "components/view_manager/public/cpp/view.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/strings/stringprintf.h" | |
9 #include "components/view_manager/public/cpp/lib/view_private.h" | |
10 #include "components/view_manager/public/cpp/util.h" | |
11 #include "components/view_manager/public/cpp/view_observer.h" | |
12 #include "components/view_manager/public/cpp/view_property.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 | |
15 namespace mojo { | |
16 | |
17 // View ------------------------------------------------------------------------ | |
18 | |
19 typedef testing::Test ViewTest; | |
20 | |
21 // Subclass with public ctor/dtor. | |
22 class TestView : public View { | |
23 public: | |
24 TestView() { | |
25 ViewPrivate(this).set_id(1); | |
26 } | |
27 ~TestView() {} | |
28 | |
29 private: | |
30 MOJO_DISALLOW_COPY_AND_ASSIGN(TestView); | |
31 }; | |
32 | |
33 TEST_F(ViewTest, AddChild) { | |
34 TestView v1; | |
35 TestView v11; | |
36 v1.AddChild(&v11); | |
37 EXPECT_EQ(1U, v1.children().size()); | |
38 } | |
39 | |
40 TEST_F(ViewTest, RemoveChild) { | |
41 TestView v1; | |
42 TestView v11; | |
43 v1.AddChild(&v11); | |
44 EXPECT_EQ(1U, v1.children().size()); | |
45 v1.RemoveChild(&v11); | |
46 EXPECT_EQ(0U, v1.children().size()); | |
47 } | |
48 | |
49 TEST_F(ViewTest, Reparent) { | |
50 TestView v1; | |
51 TestView v2; | |
52 TestView v11; | |
53 v1.AddChild(&v11); | |
54 EXPECT_EQ(1U, v1.children().size()); | |
55 v2.AddChild(&v11); | |
56 EXPECT_EQ(1U, v2.children().size()); | |
57 EXPECT_EQ(0U, v1.children().size()); | |
58 } | |
59 | |
60 TEST_F(ViewTest, Contains) { | |
61 TestView v1; | |
62 | |
63 // Direct descendant. | |
64 TestView v11; | |
65 v1.AddChild(&v11); | |
66 EXPECT_TRUE(v1.Contains(&v11)); | |
67 | |
68 // Indirect descendant. | |
69 TestView v111; | |
70 v11.AddChild(&v111); | |
71 EXPECT_TRUE(v1.Contains(&v111)); | |
72 } | |
73 | |
74 TEST_F(ViewTest, GetChildById) { | |
75 TestView v1; | |
76 ViewPrivate(&v1).set_id(1); | |
77 TestView v11; | |
78 ViewPrivate(&v11).set_id(11); | |
79 v1.AddChild(&v11); | |
80 TestView v111; | |
81 ViewPrivate(&v111).set_id(111); | |
82 v11.AddChild(&v111); | |
83 | |
84 // Find direct & indirect descendents. | |
85 EXPECT_EQ(&v11, v1.GetChildById(v11.id())); | |
86 EXPECT_EQ(&v111, v1.GetChildById(v111.id())); | |
87 } | |
88 | |
89 TEST_F(ViewTest, DrawnAndVisible) { | |
90 TestView v1; | |
91 EXPECT_TRUE(v1.visible()); | |
92 EXPECT_FALSE(v1.IsDrawn()); | |
93 | |
94 ViewPrivate(&v1).set_drawn(true); | |
95 | |
96 TestView v11; | |
97 v1.AddChild(&v11); | |
98 EXPECT_TRUE(v11.visible()); | |
99 EXPECT_TRUE(v11.IsDrawn()); | |
100 | |
101 v1.RemoveChild(&v11); | |
102 EXPECT_TRUE(v11.visible()); | |
103 EXPECT_FALSE(v11.IsDrawn()); | |
104 } | |
105 | |
106 namespace { | |
107 DEFINE_VIEW_PROPERTY_KEY(int, kIntKey, -2); | |
108 DEFINE_VIEW_PROPERTY_KEY(const char*, kStringKey, "squeamish"); | |
109 } | |
110 | |
111 TEST_F(ViewTest, Property) { | |
112 TestView v; | |
113 | |
114 // Non-existent properties should return the default values. | |
115 EXPECT_EQ(-2, v.GetLocalProperty(kIntKey)); | |
116 EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey)); | |
117 | |
118 // A set property value should be returned again (even if it's the default | |
119 // value). | |
120 v.SetLocalProperty(kIntKey, INT_MAX); | |
121 EXPECT_EQ(INT_MAX, v.GetLocalProperty(kIntKey)); | |
122 v.SetLocalProperty(kIntKey, -2); | |
123 EXPECT_EQ(-2, v.GetLocalProperty(kIntKey)); | |
124 v.SetLocalProperty(kIntKey, INT_MIN); | |
125 EXPECT_EQ(INT_MIN, v.GetLocalProperty(kIntKey)); | |
126 | |
127 v.SetLocalProperty(kStringKey, static_cast<const char*>(NULL)); | |
128 EXPECT_EQ(NULL, v.GetLocalProperty(kStringKey)); | |
129 v.SetLocalProperty(kStringKey, "squeamish"); | |
130 EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey)); | |
131 v.SetLocalProperty(kStringKey, "ossifrage"); | |
132 EXPECT_EQ(std::string("ossifrage"), v.GetLocalProperty(kStringKey)); | |
133 | |
134 // ClearProperty should restore the default value. | |
135 v.ClearLocalProperty(kIntKey); | |
136 EXPECT_EQ(-2, v.GetLocalProperty(kIntKey)); | |
137 v.ClearLocalProperty(kStringKey); | |
138 EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey)); | |
139 } | |
140 | |
141 namespace { | |
142 | |
143 class TestProperty { | |
144 public: | |
145 TestProperty() {} | |
146 virtual ~TestProperty() { last_deleted_ = this; } | |
147 static TestProperty* last_deleted() { return last_deleted_; } | |
148 | |
149 private: | |
150 static TestProperty* last_deleted_; | |
151 MOJO_DISALLOW_COPY_AND_ASSIGN(TestProperty); | |
152 }; | |
153 | |
154 TestProperty* TestProperty::last_deleted_ = NULL; | |
155 | |
156 DEFINE_OWNED_VIEW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL); | |
157 | |
158 } // namespace | |
159 | |
160 TEST_F(ViewTest, OwnedProperty) { | |
161 TestProperty* p3 = NULL; | |
162 { | |
163 TestView v; | |
164 EXPECT_EQ(NULL, v.GetLocalProperty(kOwnedKey)); | |
165 TestProperty* p1 = new TestProperty(); | |
166 v.SetLocalProperty(kOwnedKey, p1); | |
167 EXPECT_EQ(p1, v.GetLocalProperty(kOwnedKey)); | |
168 EXPECT_EQ(NULL, TestProperty::last_deleted()); | |
169 | |
170 TestProperty* p2 = new TestProperty(); | |
171 v.SetLocalProperty(kOwnedKey, p2); | |
172 EXPECT_EQ(p2, v.GetLocalProperty(kOwnedKey)); | |
173 EXPECT_EQ(p1, TestProperty::last_deleted()); | |
174 | |
175 v.ClearLocalProperty(kOwnedKey); | |
176 EXPECT_EQ(NULL, v.GetLocalProperty(kOwnedKey)); | |
177 EXPECT_EQ(p2, TestProperty::last_deleted()); | |
178 | |
179 p3 = new TestProperty(); | |
180 v.SetLocalProperty(kOwnedKey, p3); | |
181 EXPECT_EQ(p3, v.GetLocalProperty(kOwnedKey)); | |
182 EXPECT_EQ(p2, TestProperty::last_deleted()); | |
183 } | |
184 | |
185 EXPECT_EQ(p3, TestProperty::last_deleted()); | |
186 } | |
187 | |
188 // ViewObserver -------------------------------------------------------- | |
189 | |
190 typedef testing::Test ViewObserverTest; | |
191 | |
192 bool TreeChangeParamsMatch(const ViewObserver::TreeChangeParams& lhs, | |
193 const ViewObserver::TreeChangeParams& rhs) { | |
194 return lhs.target == rhs.target && lhs.old_parent == rhs.old_parent && | |
195 lhs.new_parent == rhs.new_parent && lhs.receiver == rhs.receiver; | |
196 } | |
197 | |
198 class TreeChangeObserver : public ViewObserver { | |
199 public: | |
200 explicit TreeChangeObserver(View* observee) : observee_(observee) { | |
201 observee_->AddObserver(this); | |
202 } | |
203 ~TreeChangeObserver() override { observee_->RemoveObserver(this); } | |
204 | |
205 void Reset() { | |
206 received_params_.clear(); | |
207 } | |
208 | |
209 const std::vector<TreeChangeParams>& received_params() { | |
210 return received_params_; | |
211 } | |
212 | |
213 private: | |
214 // Overridden from ViewObserver: | |
215 void OnTreeChanging(const TreeChangeParams& params) override { | |
216 received_params_.push_back(params); | |
217 } | |
218 void OnTreeChanged(const TreeChangeParams& params) override { | |
219 received_params_.push_back(params); | |
220 } | |
221 | |
222 View* observee_; | |
223 std::vector<TreeChangeParams> received_params_; | |
224 | |
225 MOJO_DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver); | |
226 }; | |
227 | |
228 // Adds/Removes v11 to v1. | |
229 TEST_F(ViewObserverTest, TreeChange_SimpleAddRemove) { | |
230 TestView v1; | |
231 TreeChangeObserver o1(&v1); | |
232 EXPECT_TRUE(o1.received_params().empty()); | |
233 | |
234 TestView v11; | |
235 TreeChangeObserver o11(&v11); | |
236 EXPECT_TRUE(o11.received_params().empty()); | |
237 | |
238 // Add. | |
239 | |
240 v1.AddChild(&v11); | |
241 | |
242 EXPECT_EQ(2U, o1.received_params().size()); | |
243 ViewObserver::TreeChangeParams p1; | |
244 p1.target = &v11; | |
245 p1.receiver = &v1; | |
246 p1.old_parent = NULL; | |
247 p1.new_parent = &v1; | |
248 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); | |
249 | |
250 EXPECT_EQ(2U, o11.received_params().size()); | |
251 ViewObserver::TreeChangeParams p11 = p1; | |
252 p11.receiver = &v11; | |
253 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); | |
254 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); | |
255 | |
256 o1.Reset(); | |
257 o11.Reset(); | |
258 EXPECT_TRUE(o1.received_params().empty()); | |
259 EXPECT_TRUE(o11.received_params().empty()); | |
260 | |
261 // Remove. | |
262 | |
263 v1.RemoveChild(&v11); | |
264 | |
265 EXPECT_EQ(2U, o1.received_params().size()); | |
266 p1.target = &v11; | |
267 p1.receiver = &v1; | |
268 p1.old_parent = &v1; | |
269 p1.new_parent = NULL; | |
270 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); | |
271 | |
272 EXPECT_EQ(2U, o11.received_params().size()); | |
273 p11 = p1; | |
274 p11.receiver = &v11; | |
275 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); | |
276 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); | |
277 } | |
278 | |
279 // Creates these two trees: | |
280 // v1 | |
281 // +- v11 | |
282 // v111 | |
283 // +- v1111 | |
284 // +- v1112 | |
285 // Then adds/removes v111 from v11. | |
286 TEST_F(ViewObserverTest, TreeChange_NestedAddRemove) { | |
287 TestView v1, v11, v111, v1111, v1112; | |
288 | |
289 // Root tree. | |
290 v1.AddChild(&v11); | |
291 | |
292 // Tree to be attached. | |
293 v111.AddChild(&v1111); | |
294 v111.AddChild(&v1112); | |
295 | |
296 TreeChangeObserver o1(&v1), o11(&v11), o111(&v111), o1111(&v1111), | |
297 o1112(&v1112); | |
298 ViewObserver::TreeChangeParams p1, p11, p111, p1111, p1112; | |
299 | |
300 // Add. | |
301 | |
302 v11.AddChild(&v111); | |
303 | |
304 EXPECT_EQ(2U, o1.received_params().size()); | |
305 p1.target = &v111; | |
306 p1.receiver = &v1; | |
307 p1.old_parent = NULL; | |
308 p1.new_parent = &v11; | |
309 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); | |
310 | |
311 EXPECT_EQ(2U, o11.received_params().size()); | |
312 p11 = p1; | |
313 p11.receiver = &v11; | |
314 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); | |
315 | |
316 EXPECT_EQ(2U, o111.received_params().size()); | |
317 p111 = p11; | |
318 p111.receiver = &v111; | |
319 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); | |
320 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); | |
321 | |
322 EXPECT_EQ(2U, o1111.received_params().size()); | |
323 p1111 = p111; | |
324 p1111.receiver = &v1111; | |
325 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front())); | |
326 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back())); | |
327 | |
328 EXPECT_EQ(2U, o1112.received_params().size()); | |
329 p1112 = p111; | |
330 p1112.receiver = &v1112; | |
331 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front())); | |
332 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back())); | |
333 | |
334 // Remove. | |
335 o1.Reset(); | |
336 o11.Reset(); | |
337 o111.Reset(); | |
338 o1111.Reset(); | |
339 o1112.Reset(); | |
340 EXPECT_TRUE(o1.received_params().empty()); | |
341 EXPECT_TRUE(o11.received_params().empty()); | |
342 EXPECT_TRUE(o111.received_params().empty()); | |
343 EXPECT_TRUE(o1111.received_params().empty()); | |
344 EXPECT_TRUE(o1112.received_params().empty()); | |
345 | |
346 v11.RemoveChild(&v111); | |
347 | |
348 EXPECT_EQ(2U, o1.received_params().size()); | |
349 p1.target = &v111; | |
350 p1.receiver = &v1; | |
351 p1.old_parent = &v11; | |
352 p1.new_parent = NULL; | |
353 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); | |
354 | |
355 EXPECT_EQ(2U, o11.received_params().size()); | |
356 p11 = p1; | |
357 p11.receiver = &v11; | |
358 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); | |
359 | |
360 EXPECT_EQ(2U, o111.received_params().size()); | |
361 p111 = p11; | |
362 p111.receiver = &v111; | |
363 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); | |
364 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); | |
365 | |
366 EXPECT_EQ(2U, o1111.received_params().size()); | |
367 p1111 = p111; | |
368 p1111.receiver = &v1111; | |
369 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front())); | |
370 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back())); | |
371 | |
372 EXPECT_EQ(2U, o1112.received_params().size()); | |
373 p1112 = p111; | |
374 p1112.receiver = &v1112; | |
375 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front())); | |
376 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back())); | |
377 } | |
378 | |
379 TEST_F(ViewObserverTest, TreeChange_Reparent) { | |
380 TestView v1, v11, v12, v111; | |
381 v1.AddChild(&v11); | |
382 v1.AddChild(&v12); | |
383 v11.AddChild(&v111); | |
384 | |
385 TreeChangeObserver o1(&v1), o11(&v11), o12(&v12), o111(&v111); | |
386 | |
387 // Reparent. | |
388 v12.AddChild(&v111); | |
389 | |
390 // v1 (root) should see both changing and changed notifications. | |
391 EXPECT_EQ(4U, o1.received_params().size()); | |
392 ViewObserver::TreeChangeParams p1; | |
393 p1.target = &v111; | |
394 p1.receiver = &v1; | |
395 p1.old_parent = &v11; | |
396 p1.new_parent = &v12; | |
397 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); | |
398 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); | |
399 | |
400 // v11 should see changing notifications. | |
401 EXPECT_EQ(2U, o11.received_params().size()); | |
402 ViewObserver::TreeChangeParams p11; | |
403 p11 = p1; | |
404 p11.receiver = &v11; | |
405 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); | |
406 | |
407 // v12 should see changed notifications. | |
408 EXPECT_EQ(2U, o12.received_params().size()); | |
409 ViewObserver::TreeChangeParams p12; | |
410 p12 = p1; | |
411 p12.receiver = &v12; | |
412 EXPECT_TRUE(TreeChangeParamsMatch(p12, o12.received_params().back())); | |
413 | |
414 // v111 should see both changing and changed notifications. | |
415 EXPECT_EQ(2U, o111.received_params().size()); | |
416 ViewObserver::TreeChangeParams p111; | |
417 p111 = p1; | |
418 p111.receiver = &v111; | |
419 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); | |
420 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); | |
421 } | |
422 | |
423 namespace { | |
424 | |
425 class OrderChangeObserver : public ViewObserver { | |
426 public: | |
427 struct Change { | |
428 View* view; | |
429 View* relative_view; | |
430 OrderDirection direction; | |
431 }; | |
432 typedef std::vector<Change> Changes; | |
433 | |
434 explicit OrderChangeObserver(View* observee) : observee_(observee) { | |
435 observee_->AddObserver(this); | |
436 } | |
437 ~OrderChangeObserver() override { observee_->RemoveObserver(this); } | |
438 | |
439 Changes GetAndClearChanges() { | |
440 Changes changes; | |
441 changes_.swap(changes); | |
442 return changes; | |
443 } | |
444 | |
445 private: | |
446 // Overridden from ViewObserver: | |
447 void OnViewReordering(View* view, | |
448 View* relative_view, | |
449 OrderDirection direction) override { | |
450 OnViewReordered(view, relative_view, direction); | |
451 } | |
452 | |
453 void OnViewReordered(View* view, | |
454 View* relative_view, | |
455 OrderDirection direction) override { | |
456 Change change; | |
457 change.view = view; | |
458 change.relative_view = relative_view; | |
459 change.direction = direction; | |
460 changes_.push_back(change); | |
461 } | |
462 | |
463 View* observee_; | |
464 Changes changes_; | |
465 | |
466 MOJO_DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver); | |
467 }; | |
468 | |
469 } // namespace | |
470 | |
471 TEST_F(ViewObserverTest, Order) { | |
472 TestView v1, v11, v12, v13; | |
473 v1.AddChild(&v11); | |
474 v1.AddChild(&v12); | |
475 v1.AddChild(&v13); | |
476 | |
477 // Order: v11, v12, v13 | |
478 EXPECT_EQ(3U, v1.children().size()); | |
479 EXPECT_EQ(&v11, v1.children().front()); | |
480 EXPECT_EQ(&v13, v1.children().back()); | |
481 | |
482 { | |
483 OrderChangeObserver observer(&v11); | |
484 | |
485 // Move v11 to front. | |
486 // Resulting order: v12, v13, v11 | |
487 v11.MoveToFront(); | |
488 EXPECT_EQ(&v12, v1.children().front()); | |
489 EXPECT_EQ(&v11, v1.children().back()); | |
490 | |
491 OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); | |
492 ASSERT_EQ(2U, changes.size()); | |
493 EXPECT_EQ(&v11, changes[0].view); | |
494 EXPECT_EQ(&v13, changes[0].relative_view); | |
495 EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[0].direction); | |
496 | |
497 EXPECT_EQ(&v11, changes[1].view); | |
498 EXPECT_EQ(&v13, changes[1].relative_view); | |
499 EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[1].direction); | |
500 } | |
501 | |
502 { | |
503 OrderChangeObserver observer(&v11); | |
504 | |
505 // Move v11 to back. | |
506 // Resulting order: v11, v12, v13 | |
507 v11.MoveToBack(); | |
508 EXPECT_EQ(&v11, v1.children().front()); | |
509 EXPECT_EQ(&v13, v1.children().back()); | |
510 | |
511 OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); | |
512 ASSERT_EQ(2U, changes.size()); | |
513 EXPECT_EQ(&v11, changes[0].view); | |
514 EXPECT_EQ(&v12, changes[0].relative_view); | |
515 EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[0].direction); | |
516 | |
517 EXPECT_EQ(&v11, changes[1].view); | |
518 EXPECT_EQ(&v12, changes[1].relative_view); | |
519 EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[1].direction); | |
520 } | |
521 | |
522 { | |
523 OrderChangeObserver observer(&v11); | |
524 | |
525 // Move v11 above v12. | |
526 // Resulting order: v12. v11, v13 | |
527 v11.Reorder(&v12, ORDER_DIRECTION_ABOVE); | |
528 EXPECT_EQ(&v12, v1.children().front()); | |
529 EXPECT_EQ(&v13, v1.children().back()); | |
530 | |
531 OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); | |
532 ASSERT_EQ(2U, changes.size()); | |
533 EXPECT_EQ(&v11, changes[0].view); | |
534 EXPECT_EQ(&v12, changes[0].relative_view); | |
535 EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[0].direction); | |
536 | |
537 EXPECT_EQ(&v11, changes[1].view); | |
538 EXPECT_EQ(&v12, changes[1].relative_view); | |
539 EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[1].direction); | |
540 } | |
541 | |
542 { | |
543 OrderChangeObserver observer(&v11); | |
544 | |
545 // Move v11 below v12. | |
546 // Resulting order: v11, v12, v13 | |
547 v11.Reorder(&v12, ORDER_DIRECTION_BELOW); | |
548 EXPECT_EQ(&v11, v1.children().front()); | |
549 EXPECT_EQ(&v13, v1.children().back()); | |
550 | |
551 OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); | |
552 ASSERT_EQ(2U, changes.size()); | |
553 EXPECT_EQ(&v11, changes[0].view); | |
554 EXPECT_EQ(&v12, changes[0].relative_view); | |
555 EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[0].direction); | |
556 | |
557 EXPECT_EQ(&v11, changes[1].view); | |
558 EXPECT_EQ(&v12, changes[1].relative_view); | |
559 EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[1].direction); | |
560 } | |
561 } | |
562 | |
563 namespace { | |
564 | |
565 typedef std::vector<std::string> Changes; | |
566 | |
567 std::string ViewIdToString(Id id) { | |
568 return (id == 0) ? "null" : | |
569 base::StringPrintf("%d,%d", HiWord(id), LoWord(id)); | |
570 } | |
571 | |
572 std::string RectToString(const Rect& rect) { | |
573 return base::StringPrintf("%d,%d %dx%d", | |
574 rect.x, rect.y, rect.width, rect.height); | |
575 } | |
576 | |
577 class BoundsChangeObserver : public ViewObserver { | |
578 public: | |
579 explicit BoundsChangeObserver(View* view) : view_(view) { | |
580 view_->AddObserver(this); | |
581 } | |
582 ~BoundsChangeObserver() override { view_->RemoveObserver(this); } | |
583 | |
584 Changes GetAndClearChanges() { | |
585 Changes changes; | |
586 changes.swap(changes_); | |
587 return changes; | |
588 } | |
589 | |
590 private: | |
591 // Overridden from ViewObserver: | |
592 void OnViewBoundsChanging(View* view, | |
593 const Rect& old_bounds, | |
594 const Rect& new_bounds) override { | |
595 changes_.push_back( | |
596 base::StringPrintf( | |
597 "view=%s old_bounds=%s new_bounds=%s phase=changing", | |
598 ViewIdToString(view->id()).c_str(), | |
599 RectToString(old_bounds).c_str(), | |
600 RectToString(new_bounds).c_str())); | |
601 } | |
602 void OnViewBoundsChanged(View* view, | |
603 const Rect& old_bounds, | |
604 const Rect& new_bounds) override { | |
605 changes_.push_back( | |
606 base::StringPrintf( | |
607 "view=%s old_bounds=%s new_bounds=%s phase=changed", | |
608 ViewIdToString(view->id()).c_str(), | |
609 RectToString(old_bounds).c_str(), | |
610 RectToString(new_bounds).c_str())); | |
611 } | |
612 | |
613 View* view_; | |
614 Changes changes_; | |
615 | |
616 MOJO_DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver); | |
617 }; | |
618 | |
619 } // namespace | |
620 | |
621 TEST_F(ViewObserverTest, SetBounds) { | |
622 TestView v1; | |
623 { | |
624 BoundsChangeObserver observer(&v1); | |
625 Rect rect; | |
626 rect.width = rect.height = 100; | |
627 v1.SetBounds(rect); | |
628 | |
629 Changes changes = observer.GetAndClearChanges(); | |
630 ASSERT_EQ(2U, changes.size()); | |
631 EXPECT_EQ( | |
632 "view=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changing", | |
633 changes[0]); | |
634 EXPECT_EQ( | |
635 "view=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changed", | |
636 changes[1]); | |
637 } | |
638 } | |
639 | |
640 namespace { | |
641 | |
642 class VisibilityChangeObserver : public ViewObserver { | |
643 public: | |
644 explicit VisibilityChangeObserver(View* view) : view_(view) { | |
645 view_->AddObserver(this); | |
646 } | |
647 ~VisibilityChangeObserver() override { view_->RemoveObserver(this); } | |
648 | |
649 Changes GetAndClearChanges() { | |
650 Changes changes; | |
651 changes.swap(changes_); | |
652 return changes; | |
653 } | |
654 | |
655 private: | |
656 // Overridden from ViewObserver: | |
657 void OnViewVisibilityChanging(View* view) override { | |
658 changes_.push_back( | |
659 base::StringPrintf("view=%s phase=changing visibility=%s", | |
660 ViewIdToString(view->id()).c_str(), | |
661 view->visible() ? "true" : "false")); | |
662 } | |
663 void OnViewVisibilityChanged(View* view) override { | |
664 changes_.push_back(base::StringPrintf("view=%s phase=changed visibility=%s", | |
665 ViewIdToString(view->id()).c_str(), | |
666 view->visible() ? "true" : "false")); | |
667 } | |
668 | |
669 View* view_; | |
670 Changes changes_; | |
671 | |
672 MOJO_DISALLOW_COPY_AND_ASSIGN(VisibilityChangeObserver); | |
673 }; | |
674 | |
675 } // namespace | |
676 | |
677 TEST_F(ViewObserverTest, SetVisible) { | |
678 TestView v1; | |
679 EXPECT_TRUE(v1.visible()); | |
680 { | |
681 // Change visibility from true to false and make sure we get notifications. | |
682 VisibilityChangeObserver observer(&v1); | |
683 v1.SetVisible(false); | |
684 | |
685 Changes changes = observer.GetAndClearChanges(); | |
686 ASSERT_EQ(2U, changes.size()); | |
687 EXPECT_EQ("view=0,1 phase=changing visibility=true", changes[0]); | |
688 EXPECT_EQ("view=0,1 phase=changed visibility=false", changes[1]); | |
689 } | |
690 { | |
691 // Set visible to existing value and verify no notifications. | |
692 VisibilityChangeObserver observer(&v1); | |
693 v1.SetVisible(false); | |
694 EXPECT_TRUE(observer.GetAndClearChanges().empty()); | |
695 } | |
696 } | |
697 | |
698 TEST_F(ViewObserverTest, SetVisibleParent) { | |
699 TestView parent; | |
700 ViewPrivate(&parent).set_id(1); | |
701 TestView child; | |
702 ViewPrivate(&child).set_id(2); | |
703 parent.AddChild(&child); | |
704 EXPECT_TRUE(parent.visible()); | |
705 EXPECT_TRUE(child.visible()); | |
706 { | |
707 // Change visibility from true to false and make sure we get notifications | |
708 // on the parent. | |
709 VisibilityChangeObserver observer(&parent); | |
710 child.SetVisible(false); | |
711 | |
712 Changes changes = observer.GetAndClearChanges(); | |
713 ASSERT_EQ(1U, changes.size()); | |
714 EXPECT_EQ("view=0,2 phase=changed visibility=false", changes[0]); | |
715 } | |
716 } | |
717 | |
718 TEST_F(ViewObserverTest, SetVisibleChild) { | |
719 TestView parent; | |
720 ViewPrivate(&parent).set_id(1); | |
721 TestView child; | |
722 ViewPrivate(&child).set_id(2); | |
723 parent.AddChild(&child); | |
724 EXPECT_TRUE(parent.visible()); | |
725 EXPECT_TRUE(child.visible()); | |
726 { | |
727 // Change visibility from true to false and make sure we get notifications | |
728 // on the child. | |
729 VisibilityChangeObserver observer(&child); | |
730 parent.SetVisible(false); | |
731 | |
732 Changes changes = observer.GetAndClearChanges(); | |
733 ASSERT_EQ(1U, changes.size()); | |
734 EXPECT_EQ("view=0,1 phase=changed visibility=false", changes[0]); | |
735 } | |
736 } | |
737 | |
738 namespace { | |
739 | |
740 class SharedPropertyChangeObserver : public ViewObserver { | |
741 public: | |
742 explicit SharedPropertyChangeObserver(View* view) : view_(view) { | |
743 view_->AddObserver(this); | |
744 } | |
745 ~SharedPropertyChangeObserver() override { view_->RemoveObserver(this); } | |
746 | |
747 Changes GetAndClearChanges() { | |
748 Changes changes; | |
749 changes.swap(changes_); | |
750 return changes; | |
751 } | |
752 | |
753 private: | |
754 // Overridden from ViewObserver: | |
755 void OnViewSharedPropertyChanged( | |
756 View* view, | |
757 const std::string& name, | |
758 const std::vector<uint8_t>* old_data, | |
759 const std::vector<uint8_t>* new_data) override { | |
760 changes_.push_back(base::StringPrintf( | |
761 "view=%s shared property changed key=%s old_value=%s new_value=%s", | |
762 ViewIdToString(view->id()).c_str(), name.c_str(), | |
763 VectorToString(old_data).c_str(), VectorToString(new_data).c_str())); | |
764 } | |
765 | |
766 std::string VectorToString(const std::vector<uint8_t>* data) { | |
767 if (!data) | |
768 return "NULL"; | |
769 std::string s; | |
770 for (char c : *data) | |
771 s += c; | |
772 return s; | |
773 } | |
774 | |
775 View* view_; | |
776 Changes changes_; | |
777 | |
778 MOJO_DISALLOW_COPY_AND_ASSIGN(SharedPropertyChangeObserver); | |
779 }; | |
780 | |
781 } // namespace | |
782 | |
783 TEST_F(ViewObserverTest, SetLocalProperty) { | |
784 TestView v1; | |
785 std::vector<uint8_t> one(1, '1'); | |
786 | |
787 { | |
788 // Change visibility from true to false and make sure we get notifications. | |
789 SharedPropertyChangeObserver observer(&v1); | |
790 v1.SetSharedProperty("one", &one); | |
791 Changes changes = observer.GetAndClearChanges(); | |
792 ASSERT_EQ(1U, changes.size()); | |
793 EXPECT_EQ( | |
794 "view=0,1 shared property changed key=one old_value=NULL new_value=1", | |
795 changes[0]); | |
796 EXPECT_EQ(1U, v1.shared_properties().size()); | |
797 } | |
798 { | |
799 // Set visible to existing value and verify no notifications. | |
800 SharedPropertyChangeObserver observer(&v1); | |
801 v1.SetSharedProperty("one", &one); | |
802 EXPECT_TRUE(observer.GetAndClearChanges().empty()); | |
803 EXPECT_EQ(1U, v1.shared_properties().size()); | |
804 } | |
805 { | |
806 // Set the value to NULL to delete it. | |
807 // Change visibility from true to false and make sure we get notifications. | |
808 SharedPropertyChangeObserver observer(&v1); | |
809 v1.SetSharedProperty("one", NULL); | |
810 Changes changes = observer.GetAndClearChanges(); | |
811 ASSERT_EQ(1U, changes.size()); | |
812 EXPECT_EQ( | |
813 "view=0,1 shared property changed key=one old_value=1 new_value=NULL", | |
814 changes[0]); | |
815 EXPECT_EQ(0U, v1.shared_properties().size()); | |
816 } | |
817 { | |
818 // Setting a null property to null shouldn't update us. | |
819 SharedPropertyChangeObserver observer(&v1); | |
820 v1.SetSharedProperty("one", NULL); | |
821 EXPECT_TRUE(observer.GetAndClearChanges().empty()); | |
822 EXPECT_EQ(0U, v1.shared_properties().size()); | |
823 } | |
824 } | |
825 | |
826 namespace { | |
827 | |
828 typedef std::pair<const void*, intptr_t> PropertyChangeInfo; | |
829 | |
830 class LocalPropertyChangeObserver : public ViewObserver { | |
831 public: | |
832 explicit LocalPropertyChangeObserver(View* view) | |
833 : view_(view), | |
834 property_key_(nullptr), | |
835 old_property_value_(-1) { | |
836 view_->AddObserver(this); | |
837 } | |
838 ~LocalPropertyChangeObserver() override { view_->RemoveObserver(this); } | |
839 | |
840 PropertyChangeInfo PropertyChangeInfoAndClear() { | |
841 PropertyChangeInfo result(property_key_, old_property_value_); | |
842 property_key_ = NULL; | |
843 old_property_value_ = -3; | |
844 return result; | |
845 } | |
846 | |
847 private: | |
848 void OnViewLocalPropertyChanged(View* window, | |
849 const void* key, | |
850 intptr_t old) override { | |
851 property_key_ = key; | |
852 old_property_value_ = old; | |
853 } | |
854 | |
855 View* view_; | |
856 const void* property_key_; | |
857 intptr_t old_property_value_; | |
858 | |
859 MOJO_DISALLOW_COPY_AND_ASSIGN(LocalPropertyChangeObserver); | |
860 }; | |
861 | |
862 } // namespace | |
863 | |
864 TEST_F(ViewObserverTest, LocalPropertyChanged) { | |
865 TestView v1; | |
866 LocalPropertyChangeObserver o(&v1); | |
867 | |
868 static const ViewProperty<int> prop = {-2}; | |
869 | |
870 v1.SetLocalProperty(&prop, 1); | |
871 EXPECT_EQ(PropertyChangeInfo(&prop, -2), o.PropertyChangeInfoAndClear()); | |
872 v1.SetLocalProperty(&prop, -2); | |
873 EXPECT_EQ(PropertyChangeInfo(&prop, 1), o.PropertyChangeInfoAndClear()); | |
874 v1.SetLocalProperty(&prop, 3); | |
875 EXPECT_EQ(PropertyChangeInfo(&prop, -2), o.PropertyChangeInfoAndClear()); | |
876 v1.ClearLocalProperty(&prop); | |
877 EXPECT_EQ(PropertyChangeInfo(&prop, 3), o.PropertyChangeInfoAndClear()); | |
878 | |
879 // Sanity check to see if |PropertyChangeInfoAndClear| really clears. | |
880 EXPECT_EQ(PropertyChangeInfo( | |
881 reinterpret_cast<const void*>(NULL), -3), o.PropertyChangeInfoAndClear()); | |
882 } | |
883 | |
884 } // namespace mojo | |
OLD | NEW |