| 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/public/cpp/view.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "base/strings/stringprintf.h" | |
| 9 #include "mojo/services/view_manager/public/cpp/lib/view_private.h" | |
| 10 #include "mojo/services/view_manager/public/cpp/util.h" | |
| 11 #include "mojo/services/view_manager/public/cpp/view_observer.h" | |
| 12 #include "mojo/services/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 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 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 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 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 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 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 virtual ~SharedPropertyChangeObserver() { 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 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 virtual ~LocalPropertyChangeObserver() { 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 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 |