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 <string> 6#include <vector> 7 8#include "base/at_exit.h" 9#include "base/auto_reset.h" 10#include "base/bind.h" 11#include "base/memory/scoped_ptr.h" 12#include "base/memory/scoped_vector.h" 13#include "base/message_loop/message_loop.h" 14#include "base/run_loop.h" 15#include "base/strings/stringprintf.h" 16#include "mojo/common/common_type_converters.h" 17#include "mojo/public/cpp/application/application.h" 18#include "mojo/public/cpp/application/connect.h" 19#include "mojo/public/cpp/bindings/lib/router.h" 20#include "mojo/service_manager/service_manager.h" 21#include "mojo/services/public/cpp/geometry/geometry_type_converters.h" 22#include "mojo/services/public/cpp/view_manager/types.h" 23#include "mojo/services/public/cpp/view_manager/util.h" 24#include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h" 25#include "mojo/services/view_manager/ids.h" 26#include "mojo/services/view_manager/test_change_tracker.h" 27#include "mojo/shell/shell_test_helper.h" 28#include "testing/gtest/include/gtest/gtest.h" 29#include "ui/gfx/geometry/rect.h" 30 31namespace mojo { 32namespace view_manager { 33namespace service { 34 35namespace { 36 37const char kTestServiceURL[] = "mojo:test_url"; 38 39// ViewManagerProxy is a proxy to an ViewManagerService. It handles invoking 40// ViewManagerService functions on the right thread in a synchronous manner 41// (each ViewManagerService cover function blocks until the response from the 42// ViewManagerService is returned). In addition it tracks the set of 43// ViewManagerClient messages received by way of a vector of Changes. Use 44// DoRunLoopUntilChangesCount() to wait for a certain number of messages to be 45// received. 46class ViewManagerProxy : public TestChangeTracker::Delegate { 47 public: 48 explicit ViewManagerProxy(TestChangeTracker* tracker) 49 : tracker_(tracker), 50 view_manager_(NULL), 51 quit_count_(0), 52 router_(NULL) { 53 SetInstance(this); 54 } 55 56 virtual ~ViewManagerProxy() {} 57 58 // Runs a message loop until the single instance has been created. 59 static ViewManagerProxy* WaitForInstance() { 60 if (!instance_) 61 RunMainLoop(); 62 ViewManagerProxy* instance = instance_; 63 instance_ = NULL; 64 return instance; 65 } 66 67 ViewManagerService* view_manager() { return view_manager_; } 68 69 // Runs the main loop until |count| changes have been received. 70 std::vector<Change> DoRunLoopUntilChangesCount(size_t count) { 71 DCHECK_EQ(0u, quit_count_); 72 if (tracker_->changes()->size() >= count) { 73 CopyChangesFromTracker(); 74 return changes_; 75 } 76 quit_count_ = count - tracker_->changes()->size(); 77 // Run the current message loop. When |count| Changes have been received, 78 // we'll quit. 79 RunMainLoop(); 80 return changes_; 81 } 82 83 const std::vector<Change>& changes() const { return changes_; } 84 85 // Destroys the connection, blocking until done. 86 void Destroy() { 87 router_->CloseMessagePipe(); 88 } 89 90 // The following functions are cover methods for ViewManagerService. They 91 // block until the result is received. 92 bool CreateNode(Id node_id) { 93 changes_.clear(); 94 bool result = false; 95 view_manager_->CreateNode(node_id, 96 base::Bind(&ViewManagerProxy::GotResult, 97 base::Unretained(this), &result)); 98 RunMainLoop(); 99 return result; 100 } 101 bool AddNode(Id parent, Id child, Id server_change_id) { 102 changes_.clear(); 103 bool result = false; 104 view_manager_->AddNode(parent, child, server_change_id, 105 base::Bind(&ViewManagerProxy::GotResult, 106 base::Unretained(this), &result)); 107 RunMainLoop(); 108 return result; 109 } 110 bool RemoveNodeFromParent(Id node_id, Id server_change_id) { 111 changes_.clear(); 112 bool result = false; 113 view_manager_->RemoveNodeFromParent(node_id, server_change_id, 114 base::Bind(&ViewManagerProxy::GotResult, 115 base::Unretained(this), &result)); 116 RunMainLoop(); 117 return result; 118 } 119 bool ReorderNode(Id node_id, 120 Id relative_node_id, 121 OrderDirection direction, 122 Id server_change_id) { 123 changes_.clear(); 124 bool result = false; 125 view_manager_->ReorderNode(node_id, relative_node_id, direction, 126 server_change_id, 127 base::Bind(&ViewManagerProxy::GotResult, 128 base::Unretained(this), &result)); 129 RunMainLoop(); 130 return result; 131 } 132 bool SetView(Id node_id, Id view_id) { 133 changes_.clear(); 134 bool result = false; 135 view_manager_->SetView(node_id, view_id, 136 base::Bind(&ViewManagerProxy::GotResult, 137 base::Unretained(this), &result)); 138 RunMainLoop(); 139 return result; 140 } 141 bool CreateView(Id view_id) { 142 changes_.clear(); 143 bool result = false; 144 view_manager_->CreateView(view_id, 145 base::Bind(&ViewManagerProxy::GotResult, 146 base::Unretained(this), &result)); 147 RunMainLoop(); 148 return result; 149 } 150 void GetNodeTree(Id node_id, std::vector<TestNode>* nodes) { 151 changes_.clear(); 152 view_manager_->GetNodeTree(node_id, 153 base::Bind(&ViewManagerProxy::GotNodeTree, 154 base::Unretained(this), nodes)); 155 RunMainLoop(); 156 } 157 bool Embed(const std::vector<Id>& nodes) { 158 changes_.clear(); 159 base::AutoReset<bool> auto_reset(&in_embed_, true); 160 bool result = false; 161 view_manager_->Embed(kTestServiceURL, Array<Id>::From(nodes), 162 base::Bind(&ViewManagerProxy::GotResult, 163 base::Unretained(this), &result)); 164 RunMainLoop(); 165 return result; 166 } 167 bool DeleteNode(Id node_id, Id server_change_id) { 168 changes_.clear(); 169 bool result = false; 170 view_manager_->DeleteNode(node_id, 171 server_change_id, 172 base::Bind(&ViewManagerProxy::GotResult, 173 base::Unretained(this), &result)); 174 RunMainLoop(); 175 return result; 176 } 177 bool DeleteView(Id view_id) { 178 changes_.clear(); 179 bool result = false; 180 view_manager_->DeleteView(view_id, 181 base::Bind(&ViewManagerProxy::GotResult, 182 base::Unretained(this), &result)); 183 RunMainLoop(); 184 return result; 185 } 186 bool SetNodeBounds(Id node_id, const gfx::Rect& bounds) { 187 changes_.clear(); 188 bool result = false; 189 view_manager_->SetNodeBounds(node_id, Rect::From(bounds), 190 base::Bind(&ViewManagerProxy::GotResult, 191 base::Unretained(this), &result)); 192 RunMainLoop(); 193 return result; 194 } 195 196 private: 197 friend class TestViewManagerClientConnection; 198 199 void set_router(mojo::internal::Router* router) { router_ = router; } 200 201 void set_view_manager(ViewManagerService* view_manager) { 202 view_manager_ = view_manager; 203 } 204 205 static void RunMainLoop() { 206 DCHECK(!main_run_loop_); 207 main_run_loop_ = new base::RunLoop; 208 main_run_loop_->Run(); 209 delete main_run_loop_; 210 main_run_loop_ = NULL; 211 } 212 213 void QuitCountReached() { 214 CopyChangesFromTracker(); 215 main_run_loop_->Quit(); 216 } 217 218 void CopyChangesFromTracker() { 219 std::vector<Change> changes; 220 tracker_->changes()->swap(changes); 221 changes_.swap(changes); 222 } 223 224 static void SetInstance(ViewManagerProxy* instance) { 225 DCHECK(!instance_); 226 instance_ = instance; 227 // Embed() runs its own run loop that is quit when the result is 228 // received. Embed() also results in a new instance. If we quit here while 229 // waiting for a Embed() we would prematurely return before we got the 230 // result from Embed(). 231 if (!in_embed_ && main_run_loop_) 232 main_run_loop_->Quit(); 233 } 234 235 // Callbacks from the various ViewManagerService functions. 236 void GotResult(bool* result_cache, bool result) { 237 *result_cache = result; 238 DCHECK(main_run_loop_); 239 main_run_loop_->Quit(); 240 } 241 242 void GotNodeTree(std::vector<TestNode>* nodes, Array<NodeDataPtr> results) { 243 NodeDatasToTestNodes(results, nodes); 244 DCHECK(main_run_loop_); 245 main_run_loop_->Quit(); 246 } 247 248 // TestChangeTracker::Delegate: 249 virtual void OnChangeAdded() OVERRIDE { 250 if (quit_count_ > 0 && --quit_count_ == 0) 251 QuitCountReached(); 252 } 253 254 static ViewManagerProxy* instance_; 255 static base::RunLoop* main_run_loop_; 256 static bool in_embed_; 257 258 TestChangeTracker* tracker_; 259 260 // MessageLoop of the test. 261 base::MessageLoop* main_loop_; 262 263 ViewManagerService* view_manager_; 264 265 // Number of changes we're waiting on until we quit the current loop. 266 size_t quit_count_; 267 268 std::vector<Change> changes_; 269 270 mojo::internal::Router* router_; 271 272 DISALLOW_COPY_AND_ASSIGN(ViewManagerProxy); 273}; 274 275// static 276ViewManagerProxy* ViewManagerProxy::instance_ = NULL; 277 278// static 279base::RunLoop* ViewManagerProxy::main_run_loop_ = NULL; 280 281// static 282bool ViewManagerProxy::in_embed_ = false; 283 284class TestViewManagerClientConnection 285 : public InterfaceImpl<ViewManagerClient> { 286 public: 287 TestViewManagerClientConnection() : connection_(&tracker_) { 288 tracker_.set_delegate(&connection_); 289 } 290 291 // InterfaceImp: 292 virtual void OnConnectionEstablished() OVERRIDE { 293 connection_.set_router(internal_state()->router()); 294 connection_.set_view_manager(client()); 295 } 296 297 // ViewMangerClient: 298 virtual void OnViewManagerConnectionEstablished( 299 ConnectionSpecificId connection_id, 300 const String& creator_url, 301 Id next_server_change_id, 302 Array<NodeDataPtr> nodes) OVERRIDE { 303 tracker_.OnViewManagerConnectionEstablished( 304 connection_id, creator_url, next_server_change_id, nodes.Pass()); 305 } 306 virtual void OnRootsAdded(Array<NodeDataPtr> nodes) OVERRIDE { 307 tracker_.OnRootsAdded(nodes.Pass()); 308 } 309 virtual void OnServerChangeIdAdvanced( 310 Id next_server_change_id) OVERRIDE { 311 tracker_.OnServerChangeIdAdvanced(next_server_change_id); 312 } 313 virtual void OnNodeBoundsChanged(Id node_id, 314 RectPtr old_bounds, 315 RectPtr new_bounds) OVERRIDE { 316 tracker_.OnNodeBoundsChanged(node_id, old_bounds.Pass(), new_bounds.Pass()); 317 } 318 virtual void OnNodeHierarchyChanged(Id node, 319 Id new_parent, 320 Id old_parent, 321 Id server_change_id, 322 Array<NodeDataPtr> nodes) OVERRIDE { 323 tracker_.OnNodeHierarchyChanged(node, new_parent, old_parent, 324 server_change_id, nodes.Pass()); 325 } 326 virtual void OnNodeReordered(Id node_id, 327 Id relative_node_id, 328 OrderDirection direction, 329 Id server_change_id) OVERRIDE { 330 tracker_.OnNodeReordered(node_id, relative_node_id, direction, 331 server_change_id); 332 } 333 virtual void OnNodeDeleted(Id node, Id server_change_id) OVERRIDE { 334 tracker_.OnNodeDeleted(node, server_change_id); 335 } 336 virtual void OnViewDeleted(Id view) OVERRIDE { 337 tracker_.OnViewDeleted(view); 338 } 339 virtual void OnNodeViewReplaced(Id node, 340 Id new_view_id, 341 Id old_view_id) OVERRIDE { 342 tracker_.OnNodeViewReplaced(node, new_view_id, old_view_id); 343 } 344 virtual void OnViewInputEvent(Id view_id, 345 EventPtr event, 346 const Callback<void()>& callback) OVERRIDE { 347 tracker_.OnViewInputEvent(view_id, event.Pass()); 348 } 349 virtual void DispatchOnViewInputEvent(Id view_id, 350 mojo::EventPtr event) OVERRIDE { 351 } 352 353 private: 354 TestChangeTracker tracker_; 355 ViewManagerProxy connection_; 356 357 DISALLOW_COPY_AND_ASSIGN(TestViewManagerClientConnection); 358}; 359 360// Used with ViewManagerService::Embed(). Creates a 361// TestViewManagerClientConnection, which creates and owns the ViewManagerProxy. 362class EmbedServiceLoader : public ServiceLoader { 363 public: 364 EmbedServiceLoader() {} 365 virtual ~EmbedServiceLoader() {} 366 367 // ServiceLoader: 368 virtual void LoadService(ServiceManager* manager, 369 const GURL& url, 370 ScopedMessagePipeHandle shell_handle) OVERRIDE { 371 scoped_ptr<Application> app(new Application(shell_handle.Pass())); 372 app->AddService<TestViewManagerClientConnection>(); 373 apps_.push_back(app.release()); 374 } 375 virtual void OnServiceError(ServiceManager* manager, 376 const GURL& url) OVERRIDE { 377 } 378 379 private: 380 ScopedVector<Application> apps_; 381 382 DISALLOW_COPY_AND_ASSIGN(EmbedServiceLoader); 383}; 384 385// Creates an id used for transport from the specified parameters. 386Id BuildNodeId(ConnectionSpecificId connection_id, 387 ConnectionSpecificId node_id) { 388 return (connection_id << 16) | node_id; 389} 390 391// Creates an id used for transport from the specified parameters. 392Id BuildViewId(ConnectionSpecificId connection_id, 393 ConnectionSpecificId view_id) { 394 return (connection_id << 16) | view_id; 395} 396 397// Callback from EmbedRoot(). |result| is the result of the 398// Embed() call and |run_loop| the nested RunLoop. 399void EmbedRootCallback(bool* result_cache, 400 base::RunLoop* run_loop, 401 bool result) { 402 *result_cache = result; 403 run_loop->Quit(); 404} 405 406// Resposible for establishing the initial ViewManagerService connection. Blocks 407// until result is determined. 408bool EmbedRoot(ViewManagerInitService* view_manager_init, 409 const std::string& url) { 410 bool result = false; 411 base::RunLoop run_loop; 412 view_manager_init->EmbedRoot(url, base::Bind(&EmbedRootCallback, 413 &result, &run_loop)); 414 run_loop.Run(); 415 return result; 416} 417 418} // namespace 419 420typedef std::vector<std::string> Changes; 421 422class ViewManagerTest : public testing::Test { 423 public: 424 ViewManagerTest() : connection_(NULL), connection2_(NULL) {} 425 426 virtual void SetUp() OVERRIDE { 427 test_helper_.Init(); 428 429 test_helper_.SetLoaderForURL( 430 scoped_ptr<ServiceLoader>(new EmbedServiceLoader()), 431 GURL(kTestServiceURL)); 432 433 ConnectToService(test_helper_.service_provider(), 434 "mojo:mojo_view_manager", 435 &view_manager_init_); 436 ASSERT_TRUE(EmbedRoot(view_manager_init_.get(), kTestServiceURL)); 437 438 connection_ = ViewManagerProxy::WaitForInstance(); 439 ASSERT_TRUE(connection_ != NULL); 440 connection_->DoRunLoopUntilChangesCount(1); 441 } 442 443 virtual void TearDown() OVERRIDE { 444 if (connection2_) 445 connection2_->Destroy(); 446 if (connection_) 447 connection_->Destroy(); 448 } 449 450 protected: 451 void EstablishSecondConnectionWithRoots(Id id1, Id id2) { 452 std::vector<Id> node_ids; 453 node_ids.push_back(id1); 454 if (id2 != 0) 455 node_ids.push_back(id2); 456 ASSERT_TRUE(connection_->Embed(node_ids)); 457 connection2_ = ViewManagerProxy::WaitForInstance(); 458 ASSERT_TRUE(connection2_ != NULL); 459 connection2_->DoRunLoopUntilChangesCount(1); 460 ASSERT_EQ(1u, connection2_->changes().size()); 461 } 462 463 // Creates a second connection to the viewmanager. 464 void EstablishSecondConnection(bool create_initial_node) { 465 if (create_initial_node) 466 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 467 ASSERT_NO_FATAL_FAILURE( 468 EstablishSecondConnectionWithRoots(BuildNodeId(1, 1), 0)); 469 const std::vector<Change>& changes(connection2_->changes()); 470 ASSERT_EQ(1u, changes.size()); 471 EXPECT_EQ("OnConnectionEstablished creator=mojo:test_url", 472 ChangesToDescription1(changes)[0]); 473 if (create_initial_node) { 474 EXPECT_EQ("[node=1,1 parent=null view=null]", 475 ChangeNodeDescription(changes)); 476 } 477 } 478 479 void DestroySecondConnection() { 480 connection2_->Destroy(); 481 connection2_ = NULL; 482 } 483 484 base::ShadowingAtExitManager at_exit_; 485 base::MessageLoop loop_; 486 shell::ShellTestHelper test_helper_; 487 488 ViewManagerInitServicePtr view_manager_init_; 489 490 ViewManagerProxy* connection_; 491 ViewManagerProxy* connection2_; 492 493 DISALLOW_COPY_AND_ASSIGN(ViewManagerTest); 494}; 495 496// TODO(sky): reenable tests: http://crbug.com/385475 497 498// Verifies client gets a valid id. 499TEST_F(ViewManagerTest, DISABLED_ValidId) { 500 // TODO(beng): this should really have the URL of the application that 501 // connected to ViewManagerInit. 502 EXPECT_EQ("OnConnectionEstablished creator=", 503 ChangesToDescription1(connection_->changes())[0]); 504 505 // All these tests assume 1 for the client id. The only real assertion here is 506 // the client id is not zero, but adding this as rest of code here assumes 1. 507 EXPECT_EQ(1, connection_->changes()[0].connection_id); 508 509 // Change ids start at 1 as well. 510 EXPECT_EQ(static_cast<Id>(1), connection_->changes()[0].change_id); 511} 512 513// Verifies two clients/connections get different ids. 514TEST_F(ViewManagerTest, DISABLED_TwoClientsGetDifferentConnectionIds) { 515 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); 516 EXPECT_EQ("OnConnectionEstablished creator=mojo:test_url", 517 ChangesToDescription1(connection2_->changes())[0]); 518 519 // It isn't strickly necessary that the second connection gets 2, but these 520 // tests are written assuming that is the case. The key thing is the 521 // connection ids of |connection_| and |connection2_| differ. 522 EXPECT_EQ(2, connection2_->changes()[0].connection_id); 523 524 // Change ids start at 1 as well. 525 EXPECT_EQ(static_cast<Id>(1), connection2_->changes()[0].change_id); 526} 527 528// Verifies client gets a valid id. 529TEST_F(ViewManagerTest, DISABLED_CreateNode) { 530 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 531 EXPECT_TRUE(connection_->changes().empty()); 532 533 // Can't create a node with the same id. 534 ASSERT_FALSE(connection_->CreateNode(BuildNodeId(1, 1))); 535 EXPECT_TRUE(connection_->changes().empty()); 536 537 // Can't create a node with a bogus connection id. 538 EXPECT_FALSE(connection_->CreateNode(BuildNodeId(2, 1))); 539 EXPECT_TRUE(connection_->changes().empty()); 540} 541 542TEST_F(ViewManagerTest, DISABLED_CreateViewFailsWithBogusConnectionId) { 543 EXPECT_FALSE(connection_->CreateView(BuildViewId(2, 1))); 544 EXPECT_TRUE(connection_->changes().empty()); 545} 546 547// Verifies hierarchy changes. 548TEST_F(ViewManagerTest, DISABLED_AddRemoveNotify) { 549 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 550 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 3))); 551 552 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); 553 554 // Make 3 a child of 2. 555 { 556 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 2), BuildNodeId(1, 3), 1)); 557 EXPECT_TRUE(connection_->changes().empty()); 558 559 connection2_->DoRunLoopUntilChangesCount(1); 560 const Changes changes(ChangesToDescription1(connection2_->changes())); 561 ASSERT_EQ(1u, changes.size()); 562 EXPECT_EQ("ServerChangeIdAdvanced 2", changes[0]); 563 } 564 565 // Remove 3 from its parent. 566 { 567 ASSERT_TRUE(connection_->RemoveNodeFromParent(BuildNodeId(1, 3), 2)); 568 EXPECT_TRUE(connection_->changes().empty()); 569 570 connection2_->DoRunLoopUntilChangesCount(1); 571 const Changes changes(ChangesToDescription1(connection2_->changes())); 572 ASSERT_EQ(1u, changes.size()); 573 EXPECT_EQ("ServerChangeIdAdvanced 3", changes[0]); 574 } 575} 576 577// Verifies AddNode fails when node is already in position. 578TEST_F(ViewManagerTest, DISABLED_AddNodeWithNoChange) { 579 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 580 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 3))); 581 582 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); 583 584 // Make 3 a child of 2. 585 { 586 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 2), BuildNodeId(1, 3), 1)); 587 588 connection2_->DoRunLoopUntilChangesCount(1); 589 const Changes changes(ChangesToDescription1(connection2_->changes())); 590 ASSERT_EQ(1u, changes.size()); 591 EXPECT_EQ("ServerChangeIdAdvanced 2", changes[0]); 592 } 593 594 // Try again, this should fail. 595 { 596 EXPECT_FALSE(connection_->AddNode(BuildNodeId(1, 2), BuildNodeId(1, 3), 2)); 597 } 598} 599 600// Verifies AddNode fails when node is already in position. 601TEST_F(ViewManagerTest, DISABLED_AddAncestorFails) { 602 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 603 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 3))); 604 605 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); 606 607 // Make 3 a child of 2. 608 { 609 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 2), BuildNodeId(1, 3), 1)); 610 connection2_->DoRunLoopUntilChangesCount(1); 611 const Changes changes(ChangesToDescription1(connection2_->changes())); 612 ASSERT_EQ(1u, changes.size()); 613 EXPECT_EQ("ServerChangeIdAdvanced 2", changes[0]); 614 } 615 616 // Try to make 2 a child of 3, this should fail since 2 is an ancestor of 3. 617 { 618 EXPECT_FALSE(connection_->AddNode(BuildNodeId(1, 3), BuildNodeId(1, 2), 2)); 619 } 620} 621 622// Verifies adding with an invalid id fails. 623TEST_F(ViewManagerTest, DISABLED_AddWithInvalidServerId) { 624 // Create two nodes. 625 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 626 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 627 628 // Make 2 a child of 1. Supply an invalid change id, which should fail. 629 ASSERT_FALSE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 2), 0)); 630} 631 632// Verifies adding to root sends right notifications. 633TEST_F(ViewManagerTest, DISABLED_AddToRoot) { 634 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 21))); 635 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 3))); 636 637 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); 638 639 // Make 3 a child of 21. 640 { 641 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 21), BuildNodeId(1, 3), 1)); 642 643 connection2_->DoRunLoopUntilChangesCount(1); 644 const Changes changes(ChangesToDescription1(connection2_->changes())); 645 ASSERT_EQ(1u, changes.size()); 646 EXPECT_EQ("ServerChangeIdAdvanced 2", changes[0]); 647 } 648 649 // Make 21 a child of 1. 650 { 651 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 21), 2)); 652 653 connection2_->DoRunLoopUntilChangesCount(1); 654 const Changes changes(ChangesToDescription1(connection2_->changes())); 655 ASSERT_EQ(1u, changes.size()); 656 EXPECT_EQ( 657 "HierarchyChanged change_id=2 node=1,21 new_parent=1,1 old_parent=null", 658 changes[0]); 659 } 660} 661 662// Verifies HierarchyChanged is correctly sent for various adds/removes. 663TEST_F(ViewManagerTest, DISABLED_NodeHierarchyChangedNodes) { 664 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 665 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 11))); 666 // Make 11 a child of 2. 667 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 2), BuildNodeId(1, 11), 1)); 668 669 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); 670 671 // Make 2 a child of 1. 672 { 673 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 2), 2)); 674 675 // Client 2 should get a hierarchy change that includes the new nodes as it 676 // has not yet seen them. 677 connection2_->DoRunLoopUntilChangesCount(1); 678 const Changes changes(ChangesToDescription1(connection2_->changes())); 679 ASSERT_EQ(1u, changes.size()); 680 EXPECT_EQ( 681 "HierarchyChanged change_id=2 node=1,2 new_parent=1,1 old_parent=null", 682 changes[0]); 683 EXPECT_EQ("[node=1,2 parent=1,1 view=null]," 684 "[node=1,11 parent=1,2 view=null]", 685 ChangeNodeDescription(connection2_->changes())); 686 } 687 688 // Add 1 to the root. 689 { 690 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 1), 3)); 691 692 // Client 2 should get a hierarchy change that includes the new nodes as it 693 // has not yet seen them. 694 connection2_->DoRunLoopUntilChangesCount(1); 695 const Changes changes(ChangesToDescription1(connection2_->changes())); 696 ASSERT_EQ(1u, changes.size()); 697 EXPECT_EQ( 698 "HierarchyChanged change_id=3 node=1,1 new_parent=null old_parent=null", 699 changes[0]); 700 EXPECT_EQ(std::string(), ChangeNodeDescription(connection2_->changes())); 701 } 702 703 // Remove 1 from its parent. 704 { 705 ASSERT_TRUE(connection_->RemoveNodeFromParent(BuildNodeId(1, 1), 4)); 706 EXPECT_TRUE(connection_->changes().empty()); 707 708 connection2_->DoRunLoopUntilChangesCount(1); 709 const Changes changes(ChangesToDescription1(connection2_->changes())); 710 ASSERT_EQ(1u, changes.size()); 711 EXPECT_EQ( 712 "HierarchyChanged change_id=4 node=1,1 new_parent=null old_parent=null", 713 changes[0]); 714 } 715 716 // Create another node, 111, parent it to 11. 717 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 111))); 718 { 719 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 11), BuildNodeId(1, 111), 720 5)); 721 722 connection2_->DoRunLoopUntilChangesCount(1); 723 const Changes changes(ChangesToDescription1(connection2_->changes())); 724 ASSERT_EQ(1u, changes.size()); 725 EXPECT_EQ( 726 "HierarchyChanged change_id=5 node=1,111 new_parent=1,11 " 727 "old_parent=null", changes[0]); 728 EXPECT_EQ("[node=1,111 parent=1,11 view=null]", 729 ChangeNodeDescription(connection2_->changes())); 730 } 731 732 // Reattach 1 to the root. 733 { 734 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 1), 6)); 735 736 connection2_->DoRunLoopUntilChangesCount(1); 737 const Changes changes(ChangesToDescription1(connection2_->changes())); 738 ASSERT_EQ(1u, changes.size()); 739 EXPECT_EQ( 740 "HierarchyChanged change_id=6 node=1,1 new_parent=null old_parent=null", 741 changes[0]); 742 EXPECT_EQ(std::string(), ChangeNodeDescription(connection2_->changes())); 743 } 744} 745 746TEST_F(ViewManagerTest, DISABLED_NodeHierarchyChangedAddingKnownToUnknown) { 747 // Create the following structure: root -> 1 -> 11 and 2->21 (2 has no 748 // parent). 749 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 750 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 11))); 751 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 752 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 21))); 753 754 // Set up the hierarchy. 755 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 1), 1)); 756 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 11), 2)); 757 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 2), BuildNodeId(1, 21), 3)); 758 759 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); 760 { 761 EXPECT_EQ("[node=1,1 parent=null view=null]," 762 "[node=1,11 parent=1,1 view=null]", 763 ChangeNodeDescription(connection2_->changes())); 764 } 765 766 // Remove 11, should result in a delete (since 11 is no longer in connection 767 // 2's root). 768 { 769 ASSERT_TRUE(connection_->RemoveNodeFromParent(BuildNodeId(1, 11), 4)); 770 771 connection2_->DoRunLoopUntilChangesCount(1); 772 const Changes changes(ChangesToDescription1(connection2_->changes())); 773 ASSERT_EQ(1u, changes.size()); 774 EXPECT_EQ("NodeDeleted change_id=4 node=1,11", changes[0]); 775 } 776 777 // Add 2 to 1. 778 { 779 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 2), 5)); 780 781 connection2_->DoRunLoopUntilChangesCount(1); 782 const Changes changes(ChangesToDescription1(connection2_->changes())); 783 ASSERT_EQ(1u, changes.size()); 784 EXPECT_EQ( 785 "HierarchyChanged change_id=5 node=1,2 new_parent=1,1 old_parent=null", 786 changes[0]); 787 EXPECT_EQ("[node=1,2 parent=1,1 view=null]," 788 "[node=1,21 parent=1,2 view=null]", 789 ChangeNodeDescription(connection2_->changes())); 790 } 791} 792 793TEST_F(ViewManagerTest, DISABLED_ReorderNode) { 794 Id node1_id = BuildNodeId(1, 1); 795 Id node2_id = BuildNodeId(1, 2); 796 Id node3_id = BuildNodeId(1, 3); 797 Id node4_id = BuildNodeId(1, 4); // Peer to 1,1 798 Id node5_id = BuildNodeId(1, 5); // Peer to 1,1 799 Id node6_id = BuildNodeId(1, 6); // Child of 1,2. 800 Id node7_id = BuildNodeId(1, 7); // Unparented. 801 Id node8_id = BuildNodeId(1, 8); // Unparented. 802 ASSERT_TRUE(connection_->CreateNode(node1_id)); 803 ASSERT_TRUE(connection_->CreateNode(node2_id)); 804 ASSERT_TRUE(connection_->CreateNode(node3_id)); 805 ASSERT_TRUE(connection_->CreateNode(node4_id)); 806 ASSERT_TRUE(connection_->CreateNode(node5_id)); 807 ASSERT_TRUE(connection_->CreateNode(node6_id)); 808 ASSERT_TRUE(connection_->CreateNode(node7_id)); 809 ASSERT_TRUE(connection_->CreateNode(node8_id)); 810 ASSERT_TRUE(connection_->AddNode(node1_id, node2_id, 1)); 811 ASSERT_TRUE(connection_->AddNode(node2_id, node6_id, 2)); 812 ASSERT_TRUE(connection_->AddNode(node1_id, node3_id, 3)); 813 ASSERT_TRUE(connection_->AddNode( 814 NodeIdToTransportId(RootNodeId()), node4_id, 4)); 815 ASSERT_TRUE(connection_->AddNode( 816 NodeIdToTransportId(RootNodeId()), node5_id, 5)); 817 818 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); 819 820 { 821 connection_->ReorderNode(node2_id, node3_id, ORDER_ABOVE, 6); 822 823 connection2_->DoRunLoopUntilChangesCount(1); 824 const Changes changes(ChangesToDescription1(connection2_->changes())); 825 ASSERT_EQ(1u, changes.size()); 826 EXPECT_EQ( 827 "Reordered change_id=6 node=1,2 relative=1,3 direction=above", 828 changes[0]); 829 } 830 831 { 832 connection_->ReorderNode(node2_id, node3_id, ORDER_BELOW, 7); 833 834 connection2_->DoRunLoopUntilChangesCount(1); 835 const Changes changes(ChangesToDescription1(connection2_->changes())); 836 ASSERT_EQ(1u, changes.size()); 837 EXPECT_EQ( 838 "Reordered change_id=7 node=1,2 relative=1,3 direction=below", 839 changes[0]); 840 } 841 842 { 843 // node2 is already below node3. 844 EXPECT_FALSE(connection_->ReorderNode(node2_id, node3_id, ORDER_BELOW, 8)); 845 } 846 847 { 848 // node4 & 5 are unknown to connection2_. 849 EXPECT_FALSE(connection2_->ReorderNode(node4_id, node5_id, ORDER_ABOVE, 8)); 850 } 851 852 { 853 // node6 & node3 have different parents. 854 EXPECT_FALSE(connection_->ReorderNode(node3_id, node6_id, ORDER_ABOVE, 8)); 855 } 856 857 { 858 // Non-existent node-ids 859 EXPECT_FALSE(connection_->ReorderNode(BuildNodeId(1, 27), 860 BuildNodeId(1, 28), 861 ORDER_ABOVE, 862 8)); 863 } 864 865 { 866 // node7 & node8 are un-parented. 867 EXPECT_FALSE(connection_->ReorderNode(node7_id, node8_id, ORDER_ABOVE, 8)); 868 } 869} 870 871// Verifies DeleteNode works. 872TEST_F(ViewManagerTest, DISABLED_DeleteNode) { 873 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 874 875 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); 876 877 // Make 2 a child of 1. 878 { 879 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 2), 1)); 880 connection2_->DoRunLoopUntilChangesCount(1); 881 const Changes changes(ChangesToDescription1(connection2_->changes())); 882 ASSERT_EQ(1u, changes.size()); 883 EXPECT_EQ("HierarchyChanged change_id=1 node=1,2 new_parent=1,1 " 884 "old_parent=null", changes[0]); 885 } 886 887 // Delete 2. 888 { 889 ASSERT_TRUE(connection_->DeleteNode(BuildNodeId(1, 2), 2)); 890 EXPECT_TRUE(connection_->changes().empty()); 891 892 connection2_->DoRunLoopUntilChangesCount(1); 893 const Changes changes(ChangesToDescription1(connection2_->changes())); 894 ASSERT_EQ(1u, changes.size()); 895 EXPECT_EQ("NodeDeleted change_id=2 node=1,2", changes[0]); 896 } 897} 898 899// Verifies DeleteNode isn't allowed from a separate connection. 900TEST_F(ViewManagerTest, DISABLED_DeleteNodeFromAnotherConnectionDisallowed) { 901 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); 902 EXPECT_FALSE(connection2_->DeleteNode(BuildNodeId(1, 1), 1)); 903} 904 905// Verifies DeleteView isn't allowed from a separate connection. 906TEST_F(ViewManagerTest, DISABLED_DeleteViewFromAnotherConnectionDisallowed) { 907 ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 1))); 908 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); 909 EXPECT_FALSE(connection2_->DeleteView(BuildViewId(1, 1))); 910} 911 912// Verifies if a node was deleted and then reused that other clients are 913// properly notified. 914TEST_F(ViewManagerTest, DISABLED_ReuseDeletedNodeId) { 915 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); 916 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 917 918 // Add 2 to 1. 919 { 920 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 2), 1)); 921 922 connection2_->DoRunLoopUntilChangesCount(1); 923 const Changes changes(ChangesToDescription1(connection2_->changes())); 924 EXPECT_EQ( 925 "HierarchyChanged change_id=1 node=1,2 new_parent=1,1 old_parent=null", 926 changes[0]); 927 EXPECT_EQ("[node=1,2 parent=1,1 view=null]", 928 ChangeNodeDescription(connection2_->changes())); 929 } 930 931 // Delete 2. 932 { 933 ASSERT_TRUE(connection_->DeleteNode(BuildNodeId(1, 2), 2)); 934 935 connection2_->DoRunLoopUntilChangesCount(1); 936 const Changes changes(ChangesToDescription1(connection2_->changes())); 937 ASSERT_EQ(1u, changes.size()); 938 EXPECT_EQ("NodeDeleted change_id=2 node=1,2", changes[0]); 939 } 940 941 // Create 2 again, and add it back to 1. Should get the same notification. 942 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 943 { 944 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 2), 3)); 945 946 connection2_->DoRunLoopUntilChangesCount(1); 947 const Changes changes(ChangesToDescription1(connection2_->changes())); 948 EXPECT_EQ( 949 "HierarchyChanged change_id=3 node=1,2 new_parent=1,1 old_parent=null", 950 changes[0]); 951 EXPECT_EQ("[node=1,2 parent=1,1 view=null]", 952 ChangeNodeDescription(connection2_->changes())); 953 } 954} 955 956// Assertions around setting a view. 957TEST_F(ViewManagerTest, DISABLED_SetView) { 958 // Create nodes 1, 2 and 3 and the view 11. Nodes 2 and 3 are parented to 1. 959 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 960 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 961 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 3))); 962 ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 11))); 963 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 2), 1)); 964 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 3), 2)); 965 966 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); 967 968 // Set view 11 on node 1. 969 { 970 ASSERT_TRUE(connection_->SetView(BuildNodeId(1, 1), 971 BuildViewId(1, 11))); 972 973 connection2_->DoRunLoopUntilChangesCount(1); 974 const Changes changes(ChangesToDescription1(connection2_->changes())); 975 ASSERT_EQ(1u, changes.size()); 976 EXPECT_EQ("ViewReplaced node=1,1 new_view=1,11 old_view=null", 977 changes[0]); 978 } 979 980 // Set view 11 on node 2. 981 { 982 ASSERT_TRUE(connection_->SetView(BuildNodeId(1, 2), BuildViewId(1, 11))); 983 984 connection2_->DoRunLoopUntilChangesCount(2); 985 const Changes changes(ChangesToDescription1(connection2_->changes())); 986 ASSERT_EQ(2u, changes.size()); 987 EXPECT_EQ("ViewReplaced node=1,1 new_view=null old_view=1,11", 988 changes[0]); 989 EXPECT_EQ("ViewReplaced node=1,2 new_view=1,11 old_view=null", 990 changes[1]); 991 } 992} 993 994// Verifies deleting a node with a view sends correct notifications. 995TEST_F(ViewManagerTest, DISABLED_DeleteNodeWithView) { 996 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 997 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 998 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 3))); 999 ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 11))); 1000 1001 // Set view 11 on node 2. 1002 ASSERT_TRUE(connection_->SetView(BuildNodeId(1, 2), BuildViewId(1, 11))); 1003 1004 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); 1005 1006 // Delete node 2. The second connection should not see this because the node 1007 // was not known to it. 1008 { 1009 ASSERT_TRUE(connection_->DeleteNode(BuildNodeId(1, 2), 1)); 1010 1011 connection2_->DoRunLoopUntilChangesCount(1); 1012 const Changes changes(ChangesToDescription1(connection2_->changes())); 1013 ASSERT_EQ(1u, changes.size()); 1014 EXPECT_EQ("ServerChangeIdAdvanced 2", changes[0]); 1015 } 1016 1017 // Parent 3 to 1. 1018 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 3), 2)); 1019 connection2_->DoRunLoopUntilChangesCount(1); 1020 1021 // Set view 11 on node 3. 1022 { 1023 ASSERT_TRUE(connection_->SetView(BuildNodeId(1, 3), BuildViewId(1, 11))); 1024 1025 connection2_->DoRunLoopUntilChangesCount(1); 1026 const Changes changes(ChangesToDescription1(connection2_->changes())); 1027 ASSERT_EQ(1u, changes.size()); 1028 EXPECT_EQ("ViewReplaced node=1,3 new_view=1,11 old_view=null", changes[0]); 1029 } 1030 1031 // Delete 3. 1032 { 1033 ASSERT_TRUE(connection_->DeleteNode(BuildNodeId(1, 3), 3)); 1034 1035 connection2_->DoRunLoopUntilChangesCount(1); 1036 const Changes changes(ChangesToDescription1(connection2_->changes())); 1037 ASSERT_EQ(1u, changes.size()); 1038 EXPECT_EQ("NodeDeleted change_id=3 node=1,3", changes[0]); 1039 } 1040} 1041 1042// Sets view from one connection on another. 1043TEST_F(ViewManagerTest, DISABLED_SetViewFromSecondConnection) { 1044 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); 1045 1046 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 1047 1048 // Create a view in the second connection. 1049 ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 51))); 1050 1051 // Attach view to node 1 in the first connection. 1052 { 1053 ASSERT_TRUE(connection2_->SetView(BuildNodeId(1, 1), BuildViewId(2, 51))); 1054 connection_->DoRunLoopUntilChangesCount(1); 1055 const Changes changes(ChangesToDescription1(connection_->changes())); 1056 ASSERT_EQ(1u, changes.size()); 1057 EXPECT_EQ("ViewReplaced node=1,1 new_view=2,51 old_view=null", changes[0]); 1058 } 1059 1060 // Shutdown the second connection and verify view is removed. 1061 { 1062 DestroySecondConnection(); 1063 connection_->DoRunLoopUntilChangesCount(2); 1064 const Changes changes(ChangesToDescription1(connection_->changes())); 1065 ASSERT_EQ(2u, changes.size()); 1066 EXPECT_EQ("ViewReplaced node=1,1 new_view=null old_view=2,51", changes[0]); 1067 EXPECT_EQ("ViewDeleted view=2,51", changes[1]); 1068 } 1069} 1070 1071// Assertions for GetNodeTree. 1072TEST_F(ViewManagerTest, DISABLED_GetNodeTree) { 1073 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); 1074 1075 // Create 11 in first connection and make it a child of 1. 1076 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 11))); 1077 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 1), 1)); 1078 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 11), 2)); 1079 1080 // Create two nodes in second connection, 2 and 3, both children of 1. 1081 ASSERT_TRUE(connection2_->CreateNode(BuildNodeId(2, 2))); 1082 ASSERT_TRUE(connection2_->CreateNode(BuildNodeId(2, 3))); 1083 ASSERT_TRUE(connection2_->AddNode(BuildNodeId(1, 1), BuildNodeId(2, 2), 3)); 1084 ASSERT_TRUE(connection2_->AddNode(BuildNodeId(1, 1), BuildNodeId(2, 3), 4)); 1085 1086 // Attach view to node 11 in the first connection. 1087 ASSERT_TRUE(connection_->CreateView(BuildViewId(1, 51))); 1088 ASSERT_TRUE(connection_->SetView(BuildNodeId(1, 11), BuildViewId(1, 51))); 1089 1090 // Verifies GetNodeTree() on the root. 1091 { 1092 std::vector<TestNode> nodes; 1093 connection_->GetNodeTree(BuildNodeId(0, 1), &nodes); 1094 ASSERT_EQ(5u, nodes.size()); 1095 EXPECT_EQ("node=0,1 parent=null view=null", nodes[0].ToString()); 1096 EXPECT_EQ("node=1,1 parent=0,1 view=null", nodes[1].ToString()); 1097 EXPECT_EQ("node=1,11 parent=1,1 view=1,51", nodes[2].ToString()); 1098 EXPECT_EQ("node=2,2 parent=1,1 view=null", nodes[3].ToString()); 1099 EXPECT_EQ("node=2,3 parent=1,1 view=null", nodes[4].ToString()); 1100 } 1101 1102 // Verifies GetNodeTree() on the node 1,1. 1103 { 1104 std::vector<TestNode> nodes; 1105 connection2_->GetNodeTree(BuildNodeId(1, 1), &nodes); 1106 ASSERT_EQ(4u, nodes.size()); 1107 EXPECT_EQ("node=1,1 parent=null view=null", nodes[0].ToString()); 1108 EXPECT_EQ("node=1,11 parent=1,1 view=1,51", nodes[1].ToString()); 1109 EXPECT_EQ("node=2,2 parent=1,1 view=null", nodes[2].ToString()); 1110 EXPECT_EQ("node=2,3 parent=1,1 view=null", nodes[3].ToString()); 1111 } 1112 1113 // Connection 2 shouldn't be able to get the root tree. 1114 { 1115 std::vector<TestNode> nodes; 1116 connection2_->GetNodeTree(BuildNodeId(0, 1), &nodes); 1117 ASSERT_EQ(0u, nodes.size()); 1118 } 1119} 1120 1121TEST_F(ViewManagerTest, DISABLED_SetNodeBounds) { 1122 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 1123 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 1), 1)); 1124 1125 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); 1126 1127 ASSERT_TRUE(connection_->SetNodeBounds(BuildNodeId(1, 1), 1128 gfx::Rect(0, 0, 100, 100))); 1129 1130 connection2_->DoRunLoopUntilChangesCount(1); 1131 const Changes changes(ChangesToDescription1(connection2_->changes())); 1132 ASSERT_EQ(1u, changes.size()); 1133 EXPECT_EQ("BoundsChanged node=1,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100", 1134 changes[0]); 1135 1136 // Should not be possible to change the bounds of a node created by another 1137 // connection. 1138 ASSERT_FALSE(connection2_->SetNodeBounds(BuildNodeId(1, 1), 1139 gfx::Rect(0, 0, 0, 0))); 1140} 1141 1142// Various assertions around SetRoots. 1143TEST_F(ViewManagerTest, DISABLED_SetRoots) { 1144 // Create 1, 2, and 3 in the first connection. 1145 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 1146 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 1147 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 3))); 1148 1149 // Parent 1 to the root. 1150 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 1), 1)); 1151 1152 // Establish the second connection and give it the roots 1 and 3. 1153 { 1154 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnectionWithRoots( 1155 BuildNodeId(1, 1), BuildNodeId(1, 3))); 1156 const Changes changes(ChangesToDescription1(connection2_->changes())); 1157 ASSERT_EQ(1u, changes.size()); 1158 EXPECT_EQ("OnConnectionEstablished creator=mojo:test_url", changes[0]); 1159 EXPECT_EQ("[node=1,1 parent=null view=null]," 1160 "[node=1,3 parent=null view=null]", 1161 ChangeNodeDescription(connection2_->changes())); 1162 } 1163 1164 // Create 4 and add it to the root, connection 2 should only get id advanced. 1165 { 1166 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 4))); 1167 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 4), 2)); 1168 1169 connection2_->DoRunLoopUntilChangesCount(1); 1170 const Changes changes(ChangesToDescription1(connection2_->changes())); 1171 ASSERT_EQ(1u, changes.size()); 1172 EXPECT_EQ("ServerChangeIdAdvanced 3", changes[0]); 1173 } 1174 1175 // Move 4 under 3, this should expose 4 to the client. 1176 { 1177 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 3), BuildNodeId(1, 4), 3)); 1178 connection2_->DoRunLoopUntilChangesCount(1); 1179 const Changes changes(ChangesToDescription1(connection2_->changes())); 1180 ASSERT_EQ(1u, changes.size()); 1181 EXPECT_EQ( 1182 "HierarchyChanged change_id=3 node=1,4 new_parent=1,3 " 1183 "old_parent=null", changes[0]); 1184 EXPECT_EQ("[node=1,4 parent=1,3 view=null]", 1185 ChangeNodeDescription(connection2_->changes())); 1186 } 1187 1188 // Move 4 under 2, since 2 isn't a root client should get a delete. 1189 { 1190 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 2), BuildNodeId(1, 4), 4)); 1191 connection2_->DoRunLoopUntilChangesCount(1); 1192 const Changes changes(ChangesToDescription1(connection2_->changes())); 1193 ASSERT_EQ(1u, changes.size()); 1194 EXPECT_EQ("NodeDeleted change_id=4 node=1,4", changes[0]); 1195 } 1196 1197 // Delete 4, client shouldn't receive a delete since it should no longer know 1198 // about 4. 1199 { 1200 ASSERT_TRUE(connection_->DeleteNode(BuildNodeId(1, 4), 5)); 1201 1202 connection2_->DoRunLoopUntilChangesCount(1); 1203 const Changes changes(ChangesToDescription1(connection2_->changes())); 1204 ASSERT_EQ(1u, changes.size()); 1205 EXPECT_EQ("ServerChangeIdAdvanced 6", changes[0]); 1206 } 1207} 1208 1209// Verify AddNode fails when trying to manipulate nodes in other roots. 1210TEST_F(ViewManagerTest, DISABLED_CantMoveNodesFromOtherRoot) { 1211 // Create 1 and 2 in the first connection. 1212 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 1213 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 1214 1215 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); 1216 1217 // Try to move 2 to be a child of 1 from connection 2. This should fail as 2 1218 // should not be able to access 1. 1219 ASSERT_FALSE(connection2_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 2), 1)); 1220 1221 // Try to reparent 1 to the root. A connection is not allowed to reparent its 1222 // roots. 1223 ASSERT_FALSE(connection2_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 1), 1)); 1224} 1225 1226// Verify RemoveNodeFromParent fails for nodes that are descendants of the 1227// roots. 1228TEST_F(ViewManagerTest, DISABLED_CantRemoveNodesInOtherRoots) { 1229 // Create 1 and 2 in the first connection and parent both to the root. 1230 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 1231 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 1232 1233 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 1), 1)); 1234 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 2), 2)); 1235 1236 // Establish the second connection and give it the root 1. 1237 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); 1238 1239 // Connection 2 should not be able to remove node 2 or 1 from its parent. 1240 ASSERT_FALSE(connection2_->RemoveNodeFromParent(BuildNodeId(1, 2), 3)); 1241 ASSERT_FALSE(connection2_->RemoveNodeFromParent(BuildNodeId(1, 1), 3)); 1242 1243 // Create nodes 10 and 11 in 2. 1244 ASSERT_TRUE(connection2_->CreateNode(BuildNodeId(2, 10))); 1245 ASSERT_TRUE(connection2_->CreateNode(BuildNodeId(2, 11))); 1246 1247 // Parent 11 to 10. 1248 ASSERT_TRUE(connection2_->AddNode(BuildNodeId(2, 10), BuildNodeId(2, 11), 3)); 1249 // Remove 11 from 10. 1250 ASSERT_TRUE(connection2_->RemoveNodeFromParent( BuildNodeId(2, 11), 4)); 1251 1252 // Verify nothing was actually removed. 1253 { 1254 std::vector<TestNode> nodes; 1255 connection_->GetNodeTree(BuildNodeId(0, 1), &nodes); 1256 ASSERT_EQ(3u, nodes.size()); 1257 EXPECT_EQ("node=0,1 parent=null view=null", nodes[0].ToString()); 1258 EXPECT_EQ("node=1,1 parent=0,1 view=null", nodes[1].ToString()); 1259 EXPECT_EQ("node=1,2 parent=0,1 view=null", nodes[2].ToString()); 1260 } 1261} 1262 1263// Verify SetView fails for nodes that are not descendants of the roots. 1264TEST_F(ViewManagerTest, DISABLED_CantRemoveSetViewInOtherRoots) { 1265 // Create 1 and 2 in the first connection and parent both to the root. 1266 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 1267 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 1268 1269 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 1), 1)); 1270 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 2), 2)); 1271 1272 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); 1273 1274 // Create a view in the second connection. 1275 ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 51))); 1276 1277 // Connection 2 should be able to set the view on node 1 (it's root), but not 1278 // on 2. 1279 ASSERT_TRUE(connection2_->SetView(BuildNodeId(1, 1), BuildViewId(2, 51))); 1280 ASSERT_FALSE(connection2_->SetView(BuildNodeId(1, 2), BuildViewId(2, 51))); 1281} 1282 1283// Verify GetNodeTree fails for nodes that are not descendants of the roots. 1284TEST_F(ViewManagerTest, DISABLED_CantGetNodeTreeOfOtherRoots) { 1285 // Create 1 and 2 in the first connection and parent both to the root. 1286 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 1287 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 1288 1289 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 1), 1)); 1290 ASSERT_TRUE(connection_->AddNode(BuildNodeId(0, 1), BuildNodeId(1, 2), 2)); 1291 1292 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); 1293 1294 std::vector<TestNode> nodes; 1295 1296 // Should get nothing for the root. 1297 connection2_->GetNodeTree(BuildNodeId(0, 1), &nodes); 1298 ASSERT_TRUE(nodes.empty()); 1299 1300 // Should get nothing for node 2. 1301 connection2_->GetNodeTree(BuildNodeId(1, 2), &nodes); 1302 ASSERT_TRUE(nodes.empty()); 1303 1304 // Should get node 1 if asked for. 1305 connection2_->GetNodeTree(BuildNodeId(1, 1), &nodes); 1306 ASSERT_EQ(1u, nodes.size()); 1307 EXPECT_EQ("node=1,1 parent=null view=null", nodes[0].ToString()); 1308} 1309 1310TEST_F(ViewManagerTest, DISABLED_ConnectTwice) { 1311 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 1312 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2))); 1313 1314 ASSERT_TRUE(connection_->AddNode(BuildNodeId(1, 1), BuildNodeId(1, 2), 1)); 1315 1316 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); 1317 1318 // Try to connect again to 1,1, this should fail as already connected to that 1319 // root. 1320 { 1321 std::vector<Id> node_ids; 1322 node_ids.push_back(BuildNodeId(1, 1)); 1323 ASSERT_FALSE(connection_->Embed(node_ids)); 1324 } 1325 1326 // Connecting to 1,2 should succeed and end up in connection2. 1327 { 1328 std::vector<Id> node_ids; 1329 node_ids.push_back(BuildNodeId(1, 2)); 1330 ASSERT_TRUE(connection_->Embed(node_ids)); 1331 connection2_->DoRunLoopUntilChangesCount(1); 1332 const Changes changes(ChangesToDescription1(connection2_->changes())); 1333 ASSERT_EQ(1u, changes.size()); 1334 EXPECT_EQ("OnRootsAdded", changes[0]); 1335 EXPECT_EQ("[node=1,2 parent=1,1 view=null]", 1336 ChangeNodeDescription(connection2_->changes())); 1337 } 1338} 1339 1340TEST_F(ViewManagerTest, DISABLED_OnViewInput) { 1341 // Create node 1 and assign a view from connection 2 to it. 1342 ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 1))); 1343 ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); 1344 ASSERT_TRUE(connection2_->CreateView(BuildViewId(2, 11))); 1345 ASSERT_TRUE(connection2_->SetView(BuildNodeId(1, 1), BuildViewId(2, 11))); 1346 1347 // Dispatch an event to the view and verify its received. 1348 { 1349 EventPtr event(Event::New()); 1350 event->action = 1; 1351 connection_->view_manager()->DispatchOnViewInputEvent( 1352 BuildViewId(2, 11), 1353 event.Pass()); 1354 connection2_->DoRunLoopUntilChangesCount(1); 1355 const Changes changes(ChangesToDescription1(connection2_->changes())); 1356 ASSERT_EQ(1u, changes.size()); 1357 EXPECT_EQ("InputEvent view=2,11 event_action=1", changes[0]); 1358 } 1359} 1360 1361// TODO(sky): add coverage of test that destroys connections and ensures other 1362// connections get deletion notification (or advanced server id). 1363 1364// TODO(sky): need to better track changes to initial connection. For example, 1365// that SetBounsdNodes/AddNode and the like don't result in messages to the 1366// originating connection. 1367 1368} // namespace service 1369} // namespace view_manager 1370} // namespace mojo 1371