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