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