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/public/cpp/view_manager/node.h" 6 7#include "base/logging.h" 8#include "base/strings/stringprintf.h" 9#include "mojo/services/public/cpp/view_manager/lib/node_private.h" 10#include "mojo/services/public/cpp/view_manager/node_observer.h" 11#include "mojo/services/public/cpp/view_manager/util.h" 12#include "testing/gtest/include/gtest/gtest.h" 13 14namespace mojo { 15namespace view_manager { 16 17// Node ------------------------------------------------------------------------ 18 19typedef testing::Test NodeTest; 20 21// Subclass with public ctor/dtor. 22class TestNode : public Node { 23 public: 24 TestNode() { 25 NodePrivate(this).set_id(1); 26 } 27 ~TestNode() {} 28 29 private: 30 DISALLOW_COPY_AND_ASSIGN(TestNode); 31}; 32 33TEST_F(NodeTest, AddChild) { 34 TestNode v1; 35 TestNode v11; 36 v1.AddChild(&v11); 37 EXPECT_EQ(1U, v1.children().size()); 38} 39 40TEST_F(NodeTest, RemoveChild) { 41 TestNode v1; 42 TestNode 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 49TEST_F(NodeTest, Reparent) { 50 TestNode v1; 51 TestNode v2; 52 TestNode 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 60TEST_F(NodeTest, Contains) { 61 TestNode v1; 62 63 // Direct descendant. 64 TestNode v11; 65 v1.AddChild(&v11); 66 EXPECT_TRUE(v1.Contains(&v11)); 67 68 // Indirect descendant. 69 TestNode v111; 70 v11.AddChild(&v111); 71 EXPECT_TRUE(v1.Contains(&v111)); 72} 73 74TEST_F(NodeTest, GetChildById) { 75 TestNode v1; 76 NodePrivate(&v1).set_id(1); 77 TestNode v11; 78 NodePrivate(&v11).set_id(11); 79 v1.AddChild(&v11); 80 TestNode v111; 81 NodePrivate(&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// NodeObserver -------------------------------------------------------- 90 91typedef testing::Test NodeObserverTest; 92 93bool TreeChangeParamsMatch(const NodeObserver::TreeChangeParams& lhs, 94 const NodeObserver::TreeChangeParams& rhs) { 95 return lhs.target == rhs.target && lhs.old_parent == rhs.old_parent && 96 lhs.new_parent == rhs.new_parent && lhs.receiver == rhs.receiver && 97 lhs.phase == rhs.phase; 98} 99 100class TreeChangeObserver : public NodeObserver { 101 public: 102 explicit TreeChangeObserver(Node* observee) : observee_(observee) { 103 observee_->AddObserver(this); 104 } 105 virtual ~TreeChangeObserver() { 106 observee_->RemoveObserver(this); 107 } 108 109 void Reset() { 110 received_params_.clear(); 111 } 112 113 const std::vector<TreeChangeParams>& received_params() { 114 return received_params_; 115 } 116 117 private: 118 // Overridden from NodeObserver: 119 virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE { 120 received_params_.push_back(params); 121 } 122 123 Node* observee_; 124 std::vector<TreeChangeParams> received_params_; 125 126 DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver); 127}; 128 129// Adds/Removes v11 to v1. 130TEST_F(NodeObserverTest, TreeChange_SimpleAddRemove) { 131 TestNode v1; 132 TreeChangeObserver o1(&v1); 133 EXPECT_TRUE(o1.received_params().empty()); 134 135 TestNode v11; 136 TreeChangeObserver o11(&v11); 137 EXPECT_TRUE(o11.received_params().empty()); 138 139 // Add. 140 141 v1.AddChild(&v11); 142 143 EXPECT_EQ(2U, o1.received_params().size()); 144 NodeObserver::TreeChangeParams p1; 145 p1.target = &v11; 146 p1.receiver = &v1; 147 p1.old_parent = NULL; 148 p1.new_parent = &v1; 149 p1.phase = NodeObserver::DISPOSITION_CHANGED; 150 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); 151 152 EXPECT_EQ(2U, o11.received_params().size()); 153 NodeObserver::TreeChangeParams p11 = p1; 154 p11.receiver = &v11; 155 p11.phase = NodeObserver::DISPOSITION_CHANGING; 156 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); 157 p11.phase = NodeObserver::DISPOSITION_CHANGED; 158 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); 159 160 o1.Reset(); 161 o11.Reset(); 162 EXPECT_TRUE(o1.received_params().empty()); 163 EXPECT_TRUE(o11.received_params().empty()); 164 165 // Remove. 166 167 v1.RemoveChild(&v11); 168 169 EXPECT_EQ(2U, o1.received_params().size()); 170 p1.target = &v11; 171 p1.receiver = &v1; 172 p1.old_parent = &v1; 173 p1.new_parent = NULL; 174 p1.phase = NodeObserver::DISPOSITION_CHANGING; 175 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); 176 177 EXPECT_EQ(2U, o11.received_params().size()); 178 p11 = p1; 179 p11.receiver = &v11; 180 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); 181 p11.phase = NodeObserver::DISPOSITION_CHANGED; 182 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); 183} 184 185// Creates these two trees: 186// v1 187// +- v11 188// v111 189// +- v1111 190// +- v1112 191// Then adds/removes v111 from v11. 192TEST_F(NodeObserverTest, TreeChange_NestedAddRemove) { 193 TestNode v1, v11, v111, v1111, v1112; 194 195 // Root tree. 196 v1.AddChild(&v11); 197 198 // Tree to be attached. 199 v111.AddChild(&v1111); 200 v111.AddChild(&v1112); 201 202 TreeChangeObserver o1(&v1), o11(&v11), o111(&v111), o1111(&v1111), 203 o1112(&v1112); 204 NodeObserver::TreeChangeParams p1, p11, p111, p1111, p1112; 205 206 // Add. 207 208 v11.AddChild(&v111); 209 210 EXPECT_EQ(2U, o1.received_params().size()); 211 p1.target = &v111; 212 p1.receiver = &v1; 213 p1.old_parent = NULL; 214 p1.new_parent = &v11; 215 p1.phase = NodeObserver::DISPOSITION_CHANGED; 216 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); 217 218 EXPECT_EQ(2U, o11.received_params().size()); 219 p11 = p1; 220 p11.receiver = &v11; 221 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); 222 223 EXPECT_EQ(2U, o111.received_params().size()); 224 p111 = p11; 225 p111.receiver = &v111; 226 p111.phase = NodeObserver::DISPOSITION_CHANGING; 227 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); 228 p111.phase = NodeObserver::DISPOSITION_CHANGED; 229 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); 230 231 EXPECT_EQ(2U, o1111.received_params().size()); 232 p1111 = p111; 233 p1111.receiver = &v1111; 234 p1111.phase = NodeObserver::DISPOSITION_CHANGING; 235 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front())); 236 p1111.phase = NodeObserver::DISPOSITION_CHANGED; 237 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back())); 238 239 EXPECT_EQ(2U, o1112.received_params().size()); 240 p1112 = p111; 241 p1112.receiver = &v1112; 242 p1112.phase = NodeObserver::DISPOSITION_CHANGING; 243 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front())); 244 p1112.phase = NodeObserver::DISPOSITION_CHANGED; 245 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back())); 246 247 // Remove. 248 o1.Reset(); 249 o11.Reset(); 250 o111.Reset(); 251 o1111.Reset(); 252 o1112.Reset(); 253 EXPECT_TRUE(o1.received_params().empty()); 254 EXPECT_TRUE(o11.received_params().empty()); 255 EXPECT_TRUE(o111.received_params().empty()); 256 EXPECT_TRUE(o1111.received_params().empty()); 257 EXPECT_TRUE(o1112.received_params().empty()); 258 259 v11.RemoveChild(&v111); 260 261 EXPECT_EQ(2U, o1.received_params().size()); 262 p1.target = &v111; 263 p1.receiver = &v1; 264 p1.old_parent = &v11; 265 p1.new_parent = NULL; 266 p1.phase = NodeObserver::DISPOSITION_CHANGING; 267 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); 268 269 EXPECT_EQ(2U, o11.received_params().size()); 270 p11 = p1; 271 p11.receiver = &v11; 272 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); 273 274 EXPECT_EQ(2U, o111.received_params().size()); 275 p111 = p11; 276 p111.receiver = &v111; 277 p111.phase = NodeObserver::DISPOSITION_CHANGING; 278 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); 279 p111.phase = NodeObserver::DISPOSITION_CHANGED; 280 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); 281 282 EXPECT_EQ(2U, o1111.received_params().size()); 283 p1111 = p111; 284 p1111.receiver = &v1111; 285 p1111.phase = NodeObserver::DISPOSITION_CHANGING; 286 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front())); 287 p1111.phase = NodeObserver::DISPOSITION_CHANGED; 288 EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back())); 289 290 EXPECT_EQ(2U, o1112.received_params().size()); 291 p1112 = p111; 292 p1112.receiver = &v1112; 293 p1112.phase = NodeObserver::DISPOSITION_CHANGING; 294 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front())); 295 p1112.phase = NodeObserver::DISPOSITION_CHANGED; 296 EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back())); 297} 298 299TEST_F(NodeObserverTest, TreeChange_Reparent) { 300 TestNode v1, v11, v12, v111; 301 v1.AddChild(&v11); 302 v1.AddChild(&v12); 303 v11.AddChild(&v111); 304 305 TreeChangeObserver o1(&v1), o11(&v11), o12(&v12), o111(&v111); 306 307 // Reparent. 308 v12.AddChild(&v111); 309 310 // v1 (root) should see both changing and changed notifications. 311 EXPECT_EQ(4U, o1.received_params().size()); 312 NodeObserver::TreeChangeParams p1; 313 p1.target = &v111; 314 p1.receiver = &v1; 315 p1.old_parent = &v11; 316 p1.new_parent = &v12; 317 p1.phase = NodeObserver::DISPOSITION_CHANGING; 318 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); 319 p1.phase = NodeObserver::DISPOSITION_CHANGED; 320 EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); 321 322 // v11 should see changing notifications. 323 EXPECT_EQ(2U, o11.received_params().size()); 324 NodeObserver::TreeChangeParams p11; 325 p11 = p1; 326 p11.receiver = &v11; 327 p11.phase = NodeObserver::DISPOSITION_CHANGING; 328 EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); 329 330 // v12 should see changed notifications. 331 EXPECT_EQ(2U, o12.received_params().size()); 332 NodeObserver::TreeChangeParams p12; 333 p12 = p1; 334 p12.receiver = &v12; 335 p12.phase = NodeObserver::DISPOSITION_CHANGED; 336 EXPECT_TRUE(TreeChangeParamsMatch(p12, o12.received_params().back())); 337 338 // v111 should see both changing and changed notifications. 339 EXPECT_EQ(2U, o111.received_params().size()); 340 NodeObserver::TreeChangeParams p111; 341 p111 = p1; 342 p111.receiver = &v111; 343 p111.phase = NodeObserver::DISPOSITION_CHANGING; 344 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); 345 p111.phase = NodeObserver::DISPOSITION_CHANGED; 346 EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); 347} 348 349namespace { 350 351class OrderChangeObserver : public NodeObserver { 352 public: 353 struct Change { 354 Node* node; 355 Node* relative_node; 356 OrderDirection direction; 357 DispositionChangePhase phase; 358 }; 359 typedef std::vector<Change> Changes; 360 361 explicit OrderChangeObserver(Node* observee) : observee_(observee) { 362 observee_->AddObserver(this); 363 } 364 virtual ~OrderChangeObserver() { 365 observee_->RemoveObserver(this); 366 } 367 368 Changes GetAndClearChanges() { 369 Changes changes; 370 changes_.swap(changes); 371 return changes; 372 } 373 374 private: 375 // Overridden from NodeObserver: 376 virtual void OnNodeReordered(Node* node, 377 Node* relative_node, 378 OrderDirection direction, 379 DispositionChangePhase phase) OVERRIDE { 380 Change change; 381 change.node = node; 382 change.relative_node = relative_node; 383 change.direction = direction; 384 change.phase = phase; 385 changes_.push_back(change); 386 } 387 388 Node* observee_; 389 Changes changes_; 390 391 DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver); 392}; 393 394} // namespace 395 396TEST_F(NodeObserverTest, Order) { 397 TestNode v1, v11, v12, v13; 398 v1.AddChild(&v11); 399 v1.AddChild(&v12); 400 v1.AddChild(&v13); 401 402 // Order: v11, v12, v13 403 EXPECT_EQ(3U, v1.children().size()); 404 EXPECT_EQ(&v11, v1.children().front()); 405 EXPECT_EQ(&v13, v1.children().back()); 406 407 { 408 OrderChangeObserver observer(&v11); 409 410 // Move v11 to front. 411 // Resulting order: v12, v13, v11 412 v11.MoveToFront(); 413 EXPECT_EQ(&v12, v1.children().front()); 414 EXPECT_EQ(&v11, v1.children().back()); 415 416 OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); 417 EXPECT_EQ(2U, changes.size()); 418 EXPECT_EQ(&v11, changes[0].node); 419 EXPECT_EQ(&v13, changes[0].relative_node); 420 EXPECT_EQ(ORDER_ABOVE, changes[0].direction); 421 EXPECT_EQ(NodeObserver::DISPOSITION_CHANGING, changes[0].phase); 422 423 EXPECT_EQ(&v11, changes[1].node); 424 EXPECT_EQ(&v13, changes[1].relative_node); 425 EXPECT_EQ(ORDER_ABOVE, changes[1].direction); 426 EXPECT_EQ(NodeObserver::DISPOSITION_CHANGED, changes[1].phase); 427 } 428 429 { 430 OrderChangeObserver observer(&v11); 431 432 // Move v11 to back. 433 // Resulting order: v11, v12, v13 434 v11.MoveToBack(); 435 EXPECT_EQ(&v11, v1.children().front()); 436 EXPECT_EQ(&v13, v1.children().back()); 437 438 OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); 439 EXPECT_EQ(2U, changes.size()); 440 EXPECT_EQ(&v11, changes[0].node); 441 EXPECT_EQ(&v12, changes[0].relative_node); 442 EXPECT_EQ(ORDER_BELOW, changes[0].direction); 443 EXPECT_EQ(NodeObserver::DISPOSITION_CHANGING, changes[0].phase); 444 445 EXPECT_EQ(&v11, changes[1].node); 446 EXPECT_EQ(&v12, changes[1].relative_node); 447 EXPECT_EQ(ORDER_BELOW, changes[1].direction); 448 EXPECT_EQ(NodeObserver::DISPOSITION_CHANGED, changes[1].phase); 449 } 450 451 { 452 OrderChangeObserver observer(&v11); 453 454 // Move v11 above v12. 455 // Resulting order: v12. v11, v13 456 v11.Reorder(&v12, ORDER_ABOVE); 457 EXPECT_EQ(&v12, v1.children().front()); 458 EXPECT_EQ(&v13, v1.children().back()); 459 460 OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); 461 EXPECT_EQ(2U, changes.size()); 462 EXPECT_EQ(&v11, changes[0].node); 463 EXPECT_EQ(&v12, changes[0].relative_node); 464 EXPECT_EQ(ORDER_ABOVE, changes[0].direction); 465 EXPECT_EQ(NodeObserver::DISPOSITION_CHANGING, changes[0].phase); 466 467 EXPECT_EQ(&v11, changes[1].node); 468 EXPECT_EQ(&v12, changes[1].relative_node); 469 EXPECT_EQ(ORDER_ABOVE, changes[1].direction); 470 EXPECT_EQ(NodeObserver::DISPOSITION_CHANGED, changes[1].phase); 471 } 472 473 { 474 OrderChangeObserver observer(&v11); 475 476 // Move v11 below v12. 477 // Resulting order: v11, v12, v13 478 v11.Reorder(&v12, ORDER_BELOW); 479 EXPECT_EQ(&v11, v1.children().front()); 480 EXPECT_EQ(&v13, v1.children().back()); 481 482 OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); 483 EXPECT_EQ(2U, changes.size()); 484 EXPECT_EQ(&v11, changes[0].node); 485 EXPECT_EQ(&v12, changes[0].relative_node); 486 EXPECT_EQ(ORDER_BELOW, changes[0].direction); 487 EXPECT_EQ(NodeObserver::DISPOSITION_CHANGING, changes[0].phase); 488 489 EXPECT_EQ(&v11, changes[1].node); 490 EXPECT_EQ(&v12, changes[1].relative_node); 491 EXPECT_EQ(ORDER_BELOW, changes[1].direction); 492 EXPECT_EQ(NodeObserver::DISPOSITION_CHANGED, changes[1].phase); 493 } 494} 495 496namespace { 497 498typedef std::vector<std::string> Changes; 499 500std::string NodeIdToString(Id id) { 501 return (id == 0) ? "null" : 502 base::StringPrintf("%d,%d", HiWord(id), LoWord(id)); 503} 504 505std::string RectToString(const gfx::Rect& rect) { 506 return base::StringPrintf("%d,%d %dx%d", 507 rect.x(), rect.y(), rect.width(), rect.height()); 508} 509 510std::string PhaseToString(NodeObserver::DispositionChangePhase phase) { 511 return phase == NodeObserver::DISPOSITION_CHANGING ? 512 "changing" : "changed"; 513} 514 515class BoundsChangeObserver : public NodeObserver { 516 public: 517 explicit BoundsChangeObserver(Node* node) : node_(node) { 518 node_->AddObserver(this); 519 } 520 virtual ~BoundsChangeObserver() { 521 node_->RemoveObserver(this); 522 } 523 524 Changes GetAndClearChanges() { 525 Changes changes; 526 changes.swap(changes_); 527 return changes; 528 } 529 530 private: 531 // Overridden from NodeObserver: 532 virtual void OnNodeBoundsChange(Node* node, 533 const gfx::Rect& old_bounds, 534 const gfx::Rect& new_bounds, 535 DispositionChangePhase phase) OVERRIDE { 536 changes_.push_back( 537 base::StringPrintf( 538 "node=%s old_bounds=%s new_bounds=%s phase=%s", 539 NodeIdToString(node->id()).c_str(), 540 RectToString(old_bounds).c_str(), 541 RectToString(new_bounds).c_str(), 542 PhaseToString(phase).c_str())); 543 } 544 545 Node* node_; 546 Changes changes_; 547 548 DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver); 549}; 550 551} // namespace 552 553TEST_F(NodeObserverTest, SetBounds) { 554 TestNode v1; 555 { 556 BoundsChangeObserver observer(&v1); 557 v1.SetBounds(gfx::Rect(0, 0, 100, 100)); 558 559 Changes changes = observer.GetAndClearChanges(); 560 EXPECT_EQ(2U, changes.size()); 561 EXPECT_EQ( 562 "node=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changing", 563 changes[0]); 564 EXPECT_EQ( 565 "node=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changed", 566 changes[1]); 567 } 568} 569 570} // namespace view_manager 571} // namespace mojo 572