| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/services/public/cpp/view_manager/view_manager.h" | 5 #include "mojo/services/public/cpp/view_manager/view_manager.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h" |
| 10 #include "mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h" |
| 9 #include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h" | 11 #include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h" |
| 10 #include "mojo/services/public/cpp/view_manager/util.h" | 12 #include "mojo/services/public/cpp/view_manager/util.h" |
| 11 #include "mojo/services/public/cpp/view_manager/view.h" | 13 #include "mojo/services/public/cpp/view_manager/view.h" |
| 12 #include "mojo/services/public/cpp/view_manager/view_observer.h" | 14 #include "mojo/services/public/cpp/view_manager/view_observer.h" |
| 13 #include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h" | 15 #include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h" |
| 14 #include "mojo/shell/shell_test_helper.h" | 16 #include "mojo/shell/shell_test_helper.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 16 | 18 |
| 17 namespace mojo { | 19 namespace mojo { |
| 18 namespace view_manager { | 20 namespace view_manager { |
| 19 | 21 |
| 20 base::RunLoop* current_run_loop = NULL; | 22 base::RunLoop* current_run_loop = NULL; |
| 21 | 23 |
| 22 void DoRunLoop() { | 24 void DoRunLoop() { |
| 23 base::RunLoop run_loop; | 25 base::RunLoop run_loop; |
| 24 current_run_loop = &run_loop; | 26 current_run_loop = &run_loop; |
| 25 current_run_loop->Run(); | 27 current_run_loop->Run(); |
| 26 current_run_loop = NULL; | 28 current_run_loop = NULL; |
| 27 } | 29 } |
| 28 | 30 |
| 29 void QuitRunLoop() { | 31 void QuitRunLoop() { |
| 30 current_run_loop->Quit(); | 32 current_run_loop->Quit(); |
| 31 } | 33 } |
| 32 | 34 |
| 35 void QuitRunLoopOnChangesAcked() { |
| 36 QuitRunLoop(); |
| 37 } |
| 38 |
| 39 void WaitForAllChangesToBeAcked(ViewManager* manager) { |
| 40 ViewManagerPrivate(manager).synchronizer()->set_changes_acked_callback( |
| 41 base::Bind(&QuitRunLoopOnChangesAcked)); |
| 42 DoRunLoop(); |
| 43 ViewManagerPrivate(manager).synchronizer()->ClearChangesAckedCallback(); |
| 44 } |
| 45 |
| 46 class ActiveViewChangedObserver : public ViewTreeNodeObserver { |
| 47 public: |
| 48 explicit ActiveViewChangedObserver(ViewTreeNode* node) |
| 49 : node_(node) {} |
| 50 virtual ~ActiveViewChangedObserver() {} |
| 51 |
| 52 private: |
| 53 // Overridden from ViewTreeNodeObserver: |
| 54 virtual void OnNodeActiveViewChange(ViewTreeNode* node, |
| 55 View* old_view, |
| 56 View* new_view, |
| 57 DispositionChangePhase phase) OVERRIDE { |
| 58 DCHECK_EQ(node, node_); |
| 59 QuitRunLoop(); |
| 60 } |
| 61 |
| 62 ViewTreeNode* node_; |
| 63 |
| 64 DISALLOW_COPY_AND_ASSIGN(ActiveViewChangedObserver); |
| 65 }; |
| 66 |
| 67 // Waits until the active view id of the supplied node changes. |
| 68 void WaitForActiveViewToChange(ViewTreeNode* node) { |
| 69 ActiveViewChangedObserver observer(node); |
| 70 node->AddObserver(&observer); |
| 71 DoRunLoop(); |
| 72 node->RemoveObserver(&observer); |
| 73 } |
| 74 |
| 75 // Spins a runloop until the tree beginning at |root| has |tree_size| nodes |
| 76 // (including |root|). |
| 77 class TreeSizeMatchesObserver : public ViewTreeNodeObserver { |
| 78 public: |
| 79 TreeSizeMatchesObserver(ViewTreeNode* tree, size_t tree_size) |
| 80 : tree_(tree), |
| 81 tree_size_(tree_size) {} |
| 82 virtual ~TreeSizeMatchesObserver() {} |
| 83 |
| 84 bool IsTreeCorrectSize() { |
| 85 return CountNodes(tree_) == tree_size_; |
| 86 } |
| 87 |
| 88 private: |
| 89 // Overridden from ViewTreeNodeObserver: |
| 90 virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE { |
| 91 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) |
| 92 return; |
| 93 if (IsTreeCorrectSize()) |
| 94 QuitRunLoop(); |
| 95 } |
| 96 |
| 97 size_t CountNodes(const ViewTreeNode* node) const { |
| 98 size_t count = 1; |
| 99 ViewTreeNode::Children::const_iterator it = node->children().begin(); |
| 100 for (; it != node->children().end(); ++it) |
| 101 count += CountNodes(*it); |
| 102 return count; |
| 103 } |
| 104 |
| 105 ViewTreeNode* tree_; |
| 106 size_t tree_size_; |
| 107 DISALLOW_COPY_AND_ASSIGN(TreeSizeMatchesObserver); |
| 108 }; |
| 109 |
| 110 void WaitForTreeSizeToMatch(ViewTreeNode* node, size_t tree_size) { |
| 111 TreeSizeMatchesObserver observer(node, tree_size); |
| 112 if (observer.IsTreeCorrectSize()) |
| 113 return; |
| 114 node->AddObserver(&observer); |
| 115 DoRunLoop(); |
| 116 node->RemoveObserver(&observer); |
| 117 } |
| 118 |
| 119 |
| 120 // Utility class that waits for the destruction of some number of nodes and |
| 121 // views. |
| 122 class DestructionObserver : public ViewTreeNodeObserver, |
| 123 public ViewObserver { |
| 124 public: |
| 125 // |nodes| or |views| can be NULL. |
| 126 DestructionObserver(std::set<TransportNodeId>* nodes, |
| 127 std::set<TransportViewId>* views) |
| 128 : nodes_(nodes), |
| 129 views_(views) {} |
| 130 |
| 131 private: |
| 132 // Overridden from ViewTreeNodeObserver: |
| 133 virtual void OnNodeDestroy( |
| 134 ViewTreeNode* node, |
| 135 ViewTreeNodeObserver::DispositionChangePhase phase) OVERRIDE { |
| 136 if (phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) |
| 137 return; |
| 138 std::set<TransportNodeId>::const_iterator it = nodes_->find(node->id()); |
| 139 if (it != nodes_->end()) |
| 140 nodes_->erase(it); |
| 141 if (CanQuit()) |
| 142 QuitRunLoop(); |
| 143 } |
| 144 |
| 145 // Overridden from ViewObserver: |
| 146 virtual void OnViewDestroy( |
| 147 View* view, |
| 148 ViewObserver::DispositionChangePhase phase) OVERRIDE { |
| 149 if (phase != ViewObserver::DISPOSITION_CHANGED) |
| 150 return; |
| 151 std::set<TransportViewId>::const_iterator it = views_->find(view->id()); |
| 152 if (it != views_->end()) |
| 153 views_->erase(it); |
| 154 if (CanQuit()) |
| 155 QuitRunLoop(); |
| 156 } |
| 157 |
| 158 bool CanQuit() { |
| 159 return (!nodes_ || nodes_->empty()) && (!views_ || views_->empty()); |
| 160 } |
| 161 |
| 162 std::set<TransportNodeId>* nodes_; |
| 163 std::set<TransportViewId>* views_; |
| 164 |
| 165 DISALLOW_COPY_AND_ASSIGN(DestructionObserver); |
| 166 }; |
| 167 |
| 168 void WaitForDestruction(ViewManager* view_manager, |
| 169 std::set<TransportNodeId>* nodes, |
| 170 std::set<TransportViewId>* views) { |
| 171 DestructionObserver observer(nodes, views); |
| 172 DCHECK(nodes || views); |
| 173 if (nodes) { |
| 174 for (std::set<TransportNodeId>::const_iterator it = nodes->begin(); |
| 175 it != nodes->end(); ++it) { |
| 176 view_manager->GetNodeById(*it)->AddObserver(&observer); |
| 177 } |
| 178 } |
| 179 if (views) { |
| 180 for (std::set<TransportViewId>::const_iterator it = views->begin(); |
| 181 it != views->end(); ++it) { |
| 182 view_manager->GetViewById(*it)->AddObserver(&observer); |
| 183 } |
| 184 } |
| 185 DoRunLoop(); |
| 186 } |
| 187 |
| 33 // ViewManager ----------------------------------------------------------------- | 188 // ViewManager ----------------------------------------------------------------- |
| 34 | 189 |
| 35 // These tests model synchronization of two peer connections to the view manager | 190 // These tests model synchronization of two peer connections to the view manager |
| 36 // service, that are given access to some root node. | 191 // service, that are given access to some root node. |
| 37 | 192 |
| 38 class ViewManagerTest : public testing::Test { | 193 class ViewManagerTest : public testing::Test { |
| 39 public: | 194 public: |
| 40 ViewManagerTest() : commit_count_(0) {} | 195 ViewManagerTest() : commit_count_(0) {} |
| 41 | 196 |
| 42 protected: | 197 protected: |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 // Overridden from ViewTreeNodeObserver: | 249 // Overridden from ViewTreeNodeObserver: |
| 95 virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE { | 250 virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE { |
| 96 if (ShouldQuitRunLoop(params)) | 251 if (ShouldQuitRunLoop(params)) |
| 97 QuitRunLoop(); | 252 QuitRunLoop(); |
| 98 } | 253 } |
| 99 | 254 |
| 100 ViewManager* view_manager_; | 255 ViewManager* view_manager_; |
| 101 DISALLOW_COPY_AND_ASSIGN(TreeObserverBase); | 256 DISALLOW_COPY_AND_ASSIGN(TreeObserverBase); |
| 102 }; | 257 }; |
| 103 | 258 |
| 104 // Spins a runloop until the tree beginning at |root| has |tree_size| nodes | |
| 105 // (including |root|). | |
| 106 class TreeSizeMatchesWaiter : public TreeObserverBase { | |
| 107 public: | |
| 108 TreeSizeMatchesWaiter(ViewManager* view_manager, size_t tree_size) | |
| 109 : TreeObserverBase(view_manager), | |
| 110 tree_size_(tree_size) { | |
| 111 DoRunLoop(); | |
| 112 } | |
| 113 virtual ~TreeSizeMatchesWaiter() {} | |
| 114 | |
| 115 private: | |
| 116 // Overridden from TreeObserverBase: | |
| 117 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { | |
| 118 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) | |
| 119 return false; | |
| 120 return CountNodes(view_manager()->tree()) == tree_size_; | |
| 121 } | |
| 122 | |
| 123 size_t CountNodes(ViewTreeNode* node) const { | |
| 124 size_t count = 1; | |
| 125 ViewTreeNode::Children::const_iterator it = node->children().begin(); | |
| 126 for (; it != node->children().end(); ++it) | |
| 127 count += CountNodes(*it); | |
| 128 return count; | |
| 129 } | |
| 130 | |
| 131 size_t tree_size_; | |
| 132 DISALLOW_COPY_AND_ASSIGN(TreeSizeMatchesWaiter); | |
| 133 }; | |
| 134 | |
| 135 | |
| 136 class HierarchyChanged_NodeCreatedObserver : public TreeObserverBase { | 259 class HierarchyChanged_NodeCreatedObserver : public TreeObserverBase { |
| 137 public: | 260 public: |
| 138 explicit HierarchyChanged_NodeCreatedObserver(ViewManager* view_manager) | 261 explicit HierarchyChanged_NodeCreatedObserver(ViewManager* view_manager) |
| 139 : TreeObserverBase(view_manager) {} | 262 : TreeObserverBase(view_manager) {} |
| 140 virtual ~HierarchyChanged_NodeCreatedObserver() {} | 263 virtual ~HierarchyChanged_NodeCreatedObserver() {} |
| 141 | 264 |
| 142 private: | 265 private: |
| 143 // Overridden from TreeObserverBase: | 266 // Overridden from TreeObserverBase: |
| 144 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { | 267 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { |
| 145 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) | 268 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 TransportNodeId old_parent_id_; | 309 TransportNodeId old_parent_id_; |
| 187 TransportNodeId new_parent_id_; | 310 TransportNodeId new_parent_id_; |
| 188 | 311 |
| 189 DISALLOW_COPY_AND_ASSIGN(HierarchyChanged_NodeMovedObserver); | 312 DISALLOW_COPY_AND_ASSIGN(HierarchyChanged_NodeMovedObserver); |
| 190 }; | 313 }; |
| 191 | 314 |
| 192 TEST_F(ViewManagerTest, HierarchyChanged_NodeMoved) { | 315 TEST_F(ViewManagerTest, HierarchyChanged_NodeMoved) { |
| 193 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 316 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 194 ViewTreeNode* node2 = CreateNodeInParent(view_manager_1()->tree()); | 317 ViewTreeNode* node2 = CreateNodeInParent(view_manager_1()->tree()); |
| 195 ViewTreeNode* node21 = CreateNodeInParent(node2); | 318 ViewTreeNode* node21 = CreateNodeInParent(node2); |
| 196 TreeSizeMatchesWaiter waiter(view_manager_2(), 4); | 319 WaitForTreeSizeToMatch(view_manager_2()->tree(), 4); |
| 197 | 320 |
| 198 HierarchyChanged_NodeMovedObserver observer(view_manager_2(), | 321 HierarchyChanged_NodeMovedObserver observer(view_manager_2(), |
| 199 node2->id(), | 322 node2->id(), |
| 200 node1->id()); | 323 node1->id()); |
| 201 | 324 |
| 202 node1->AddChild(node21); | 325 node1->AddChild(node21); |
| 203 DoRunLoop(); | 326 DoRunLoop(); |
| 204 | 327 |
| 205 ViewTreeNode* tree2 = view_manager_2()->tree(); | 328 ViewTreeNode* tree2 = view_manager_2()->tree(); |
| 206 | 329 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 227 return params.receiver == view_manager()->tree() && | 350 return params.receiver == view_manager()->tree() && |
| 228 params.old_parent->id() == params.receiver->id() && | 351 params.old_parent->id() == params.receiver->id() && |
| 229 params.new_parent == 0; | 352 params.new_parent == 0; |
| 230 } | 353 } |
| 231 | 354 |
| 232 DISALLOW_COPY_AND_ASSIGN(HierarchyChanged_NodeRemovedObserver); | 355 DISALLOW_COPY_AND_ASSIGN(HierarchyChanged_NodeRemovedObserver); |
| 233 }; | 356 }; |
| 234 | 357 |
| 235 TEST_F(ViewManagerTest, HierarchyChanged_NodeRemoved) { | 358 TEST_F(ViewManagerTest, HierarchyChanged_NodeRemoved) { |
| 236 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 359 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 237 TreeSizeMatchesWaiter waiter(view_manager_2(), 2); | 360 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); |
| 238 | 361 |
| 239 HierarchyChanged_NodeRemovedObserver observer(view_manager_2()); | 362 HierarchyChanged_NodeRemovedObserver observer(view_manager_2()); |
| 240 | 363 |
| 241 view_manager_1()->tree()->RemoveChild(node1); | 364 view_manager_1()->tree()->RemoveChild(node1); |
| 242 DoRunLoop(); | 365 DoRunLoop(); |
| 243 | 366 |
| 244 ViewTreeNode* tree2 = view_manager_2()->tree(); | 367 ViewTreeNode* tree2 = view_manager_2()->tree(); |
| 245 | 368 |
| 246 EXPECT_TRUE(tree2->children().empty()); | 369 EXPECT_TRUE(tree2->children().empty()); |
| 247 } | 370 } |
| 248 | 371 |
| 249 // Utility class that waits for the destruction of some number of nodes and | |
| 250 // views. | |
| 251 class DestructionWaiter : public ViewTreeNodeObserver, | |
| 252 public ViewObserver { | |
| 253 public: | |
| 254 // |nodes| or |views| can be NULL. | |
| 255 DestructionWaiter(ViewManager* view_manager, | |
| 256 std::set<TransportNodeId>* nodes, | |
| 257 std::set<TransportViewId>* views) | |
| 258 : nodes_(nodes), | |
| 259 views_(views) { | |
| 260 DCHECK(nodes || views); | |
| 261 if (nodes) { | |
| 262 for (std::set<TransportNodeId>::const_iterator it = nodes->begin(); | |
| 263 it != nodes->end(); ++it) { | |
| 264 view_manager->GetNodeById(*it)->AddObserver(this); | |
| 265 } | |
| 266 } | |
| 267 if (views) { | |
| 268 for (std::set<TransportViewId>::const_iterator it = views->begin(); | |
| 269 it != views->end(); ++it) { | |
| 270 view_manager->GetViewById(*it)->AddObserver(this); | |
| 271 } | |
| 272 } | |
| 273 DoRunLoop(); | |
| 274 } | |
| 275 | |
| 276 private: | |
| 277 // Overridden from ViewTreeNodeObserver: | |
| 278 virtual void OnNodeDestroy( | |
| 279 ViewTreeNode* node, | |
| 280 ViewTreeNodeObserver::DispositionChangePhase phase) OVERRIDE { | |
| 281 if (phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) | |
| 282 return; | |
| 283 std::set<TransportNodeId>::const_iterator it = nodes_->find(node->id()); | |
| 284 if (it != nodes_->end()) | |
| 285 nodes_->erase(it); | |
| 286 if (CanQuit()) | |
| 287 QuitRunLoop(); | |
| 288 } | |
| 289 | |
| 290 // Overridden from ViewObserver: | |
| 291 virtual void OnViewDestroy( | |
| 292 View* view, | |
| 293 ViewObserver::DispositionChangePhase phase) OVERRIDE { | |
| 294 if (phase != ViewObserver::DISPOSITION_CHANGED) | |
| 295 return; | |
| 296 std::set<TransportViewId>::const_iterator it = views_->find(view->id()); | |
| 297 if (it != views_->end()) | |
| 298 views_->erase(it); | |
| 299 if (CanQuit()) | |
| 300 QuitRunLoop(); | |
| 301 } | |
| 302 | |
| 303 bool CanQuit() { | |
| 304 return (!nodes_ || nodes_->empty()) && (!views_ || views_->empty()); | |
| 305 } | |
| 306 | |
| 307 std::set<TransportNodeId>* nodes_; | |
| 308 std::set<TransportViewId>* views_; | |
| 309 | |
| 310 DISALLOW_COPY_AND_ASSIGN(DestructionWaiter); | |
| 311 }; | |
| 312 | |
| 313 TEST_F(ViewManagerTest, NodeDestroyed) { | 372 TEST_F(ViewManagerTest, NodeDestroyed) { |
| 314 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 373 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 315 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); | 374 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); |
| 316 | 375 |
| 317 // |node1| will be deleted after calling Destroy() below. | 376 // |node1| will be deleted after calling Destroy() below. |
| 318 TransportNodeId id = node1->id(); | 377 TransportNodeId id = node1->id(); |
| 319 node1->Destroy(); | 378 node1->Destroy(); |
| 320 | 379 |
| 321 std::set<TransportNodeId> nodes; | 380 std::set<TransportNodeId> nodes; |
| 322 nodes.insert(id); | 381 nodes.insert(id); |
| 323 DestructionWaiter destroyed_waiter(view_manager_2(), &nodes, NULL); | 382 WaitForDestruction(view_manager_2(), &nodes, NULL); |
| 324 | 383 |
| 325 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); | 384 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); |
| 326 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(id)); | 385 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(id)); |
| 327 } | 386 } |
| 328 | 387 |
| 329 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNode) { | 388 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNode) { |
| 330 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 389 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 331 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); | 390 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); |
| 332 | 391 |
| 333 TransportNodeId id = node1->id(); | 392 TransportNodeId id = node1->id(); |
| 334 DestroyViewManager1(); | 393 DestroyViewManager1(); |
| 335 std::set<TransportNodeId> nodes; | 394 std::set<TransportNodeId> nodes; |
| 336 nodes.insert(id); | 395 nodes.insert(id); |
| 337 DestructionWaiter destroyed_waiter(view_manager_2(), &nodes, NULL); | 396 WaitForDestruction(view_manager_2(), &nodes, NULL); |
| 338 | 397 |
| 339 // tree() should still be valid, since it's owned by neither connection. | 398 // tree() should still be valid, since it's owned by neither connection. |
| 340 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); | 399 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); |
| 341 } | 400 } |
| 342 | 401 |
| 343 // Waits until the active view id of the supplied node changes. | |
| 344 class ActiveViewChangedWaiter : public ViewTreeNodeObserver { | |
| 345 public: | |
| 346 explicit ActiveViewChangedWaiter(ViewTreeNode* node) | |
| 347 : node_(node) { | |
| 348 node_->AddObserver(this); | |
| 349 DoRunLoop(); | |
| 350 } | |
| 351 virtual ~ActiveViewChangedWaiter() { | |
| 352 node_->RemoveObserver(this); | |
| 353 } | |
| 354 | |
| 355 private: | |
| 356 // Overridden from ViewTreeNodeObserver: | |
| 357 virtual void OnNodeActiveViewChange(ViewTreeNode* node, | |
| 358 View* old_view, | |
| 359 View* new_view, | |
| 360 DispositionChangePhase phase) OVERRIDE { | |
| 361 DCHECK_EQ(node, node_); | |
| 362 QuitRunLoop(); | |
| 363 } | |
| 364 | |
| 365 ViewTreeNode* node_; | |
| 366 | |
| 367 DISALLOW_COPY_AND_ASSIGN(ActiveViewChangedWaiter); | |
| 368 }; | |
| 369 | |
| 370 TEST_F(ViewManagerTest, SetActiveView) { | 402 TEST_F(ViewManagerTest, SetActiveView) { |
| 371 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 403 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 372 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); | 404 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); |
| 373 | 405 |
| 374 View* view1 = View::Create(view_manager_1()); | 406 View* view1 = View::Create(view_manager_1()); |
| 375 node1->SetActiveView(view1); | 407 node1->SetActiveView(view1); |
| 376 | 408 |
| 377 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); | 409 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); |
| 378 ActiveViewChangedWaiter waiter(node1_2); | 410 WaitForActiveViewToChange(node1_2); |
| 379 | 411 |
| 380 EXPECT_EQ(node1_2->active_view()->id(), view1->id()); | 412 EXPECT_EQ(node1_2->active_view()->id(), view1->id()); |
| 381 } | 413 } |
| 382 | 414 |
| 383 TEST_F(ViewManagerTest, DestroyView) { | 415 TEST_F(ViewManagerTest, DestroyView) { |
| 384 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 416 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 385 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); | 417 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); |
| 386 | 418 |
| 387 View* view1 = View::Create(view_manager_1()); | 419 View* view1 = View::Create(view_manager_1()); |
| 388 node1->SetActiveView(view1); | 420 node1->SetActiveView(view1); |
| 389 | 421 |
| 390 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); | 422 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); |
| 391 ActiveViewChangedWaiter active_view_waiter(node1_2); | 423 WaitForActiveViewToChange(node1_2); |
| 392 | 424 |
| 393 TransportViewId view1_id = view1->id(); | 425 TransportViewId view1_id = view1->id(); |
| 394 view1->Destroy(); | 426 view1->Destroy(); |
| 395 | 427 |
| 396 std::set<TransportViewId> views; | 428 std::set<TransportViewId> views; |
| 397 views.insert(view1_id); | 429 views.insert(view1_id); |
| 398 DestructionWaiter destruction_waiter(view_manager_2(), NULL, &views); | 430 WaitForDestruction(view_manager_2(), NULL, &views); |
| 399 EXPECT_EQ(NULL, node1_2->active_view()); | 431 EXPECT_EQ(NULL, node1_2->active_view()); |
| 400 EXPECT_EQ(NULL, view_manager_2()->GetViewById(view1_id)); | 432 EXPECT_EQ(NULL, view_manager_2()->GetViewById(view1_id)); |
| 401 } | 433 } |
| 402 | 434 |
| 403 // Destroying the connection that created a node and view should result in that | 435 // Destroying the connection that created a node and view should result in that |
| 404 // node and view disappearing from all connections that see them. | 436 // node and view disappearing from all connections that see them. |
| 405 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNodeAndView) { | 437 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNodeAndView) { |
| 406 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 438 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 407 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); | 439 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); |
| 408 | 440 |
| 409 View* view1 = View::Create(view_manager_1()); | 441 View* view1 = View::Create(view_manager_1()); |
| 410 node1->SetActiveView(view1); | 442 node1->SetActiveView(view1); |
| 411 | 443 |
| 412 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); | 444 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); |
| 413 { | 445 WaitForActiveViewToChange(node1_2); |
| 414 ActiveViewChangedWaiter active_view_waiter(node1_2); | |
| 415 } | |
| 416 | 446 |
| 417 TransportNodeId node1_id = node1->id(); | 447 TransportNodeId node1_id = node1->id(); |
| 418 TransportViewId view1_id = view1->id(); | 448 TransportViewId view1_id = view1->id(); |
| 419 | 449 |
| 420 DestroyViewManager1(); | 450 DestroyViewManager1(); |
| 421 std::set<TransportNodeId> observed_nodes; | 451 std::set<TransportNodeId> observed_nodes; |
| 422 observed_nodes.insert(node1_id); | 452 observed_nodes.insert(node1_id); |
| 423 std::set<TransportViewId> observed_views; | 453 std::set<TransportViewId> observed_views; |
| 424 observed_views.insert(view1_id); | 454 observed_views.insert(view1_id); |
| 425 DestructionWaiter destruction_waiter(view_manager_2(), | 455 WaitForDestruction(view_manager_2(), &observed_nodes, &observed_views); |
| 426 &observed_nodes, | |
| 427 &observed_views); | |
| 428 | 456 |
| 429 // tree() should still be valid, since it's owned by neither connection. | 457 // tree() should still be valid, since it's owned by neither connection. |
| 430 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); | 458 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); |
| 431 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(node1_id)); | 459 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(node1_id)); |
| 432 EXPECT_EQ(NULL, view_manager_2()->GetViewById(view1_id)); | 460 EXPECT_EQ(NULL, view_manager_2()->GetViewById(view1_id)); |
| 433 } | 461 } |
| 434 | 462 |
| 435 // This test validates the following scenario: | 463 // This test validates the following scenario: |
| 436 // - a node originating from one connection | 464 // - a node originating from one connection |
| 437 // - a view originating from a second connection | 465 // - a view originating from a second connection |
| 438 // + the connection originating the node is destroyed | 466 // + the connection originating the node is destroyed |
| 439 // -> the view should still exist (since the second connection is live) but | 467 // -> the view should still exist (since the second connection is live) but |
| 440 // should be disconnected from any nodes. | 468 // should be disconnected from any nodes. |
| 441 TEST_F(ViewManagerTest, | 469 TEST_F(ViewManagerTest, |
| 442 ViewManagerDestroyed_CleanupNodeAndViewFromDifferentConnections) { | 470 ViewManagerDestroyed_CleanupNodeAndViewFromDifferentConnections) { |
| 443 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 471 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 444 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); | 472 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); |
| 445 | 473 |
| 446 View* view1_2 = View::Create(view_manager_2()); | 474 View* view1_2 = View::Create(view_manager_2()); |
| 447 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); | 475 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); |
| 448 node1_2->SetActiveView(view1_2); | 476 node1_2->SetActiveView(view1_2); |
| 449 | 477 WaitForActiveViewToChange(node1); |
| 450 { | |
| 451 ActiveViewChangedWaiter active_view_waiter(node1); | |
| 452 } | |
| 453 | 478 |
| 454 TransportNodeId node1_id = node1->id(); | 479 TransportNodeId node1_id = node1->id(); |
| 455 TransportViewId view1_2_id = view1_2->id(); | 480 TransportViewId view1_2_id = view1_2->id(); |
| 456 | 481 |
| 457 DestroyViewManager1(); | 482 DestroyViewManager1(); |
| 458 std::set<TransportNodeId> nodes; | 483 std::set<TransportNodeId> nodes; |
| 459 nodes.insert(node1_id); | 484 nodes.insert(node1_id); |
| 460 DestructionWaiter destruction_waiter(view_manager_2(), &nodes, NULL); | 485 WaitForDestruction(view_manager_2(), &nodes, NULL); |
| 461 | 486 |
| 462 // tree() should still be valid, since it's owned by neither connection. | 487 // tree() should still be valid, since it's owned by neither connection. |
| 463 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); | 488 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); |
| 464 // node1 was owned by the first connection, so it should be gone. | 489 // node1 was owned by the first connection, so it should be gone. |
| 465 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(node1_id)); | 490 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(node1_id)); |
| 466 // view1_2 was owned by the second connection, so it should still exist, but | 491 // view1_2 was owned by the second connection, so it should still exist, but |
| 467 // disconnected from the node tree. | 492 // disconnected from the node tree. |
| 468 View* another_view1_2 = view_manager_2()->GetViewById(view1_2_id); | 493 View* another_view1_2 = view_manager_2()->GetViewById(view1_2_id); |
| 469 EXPECT_EQ(view1_2, another_view1_2); | 494 EXPECT_EQ(view1_2, another_view1_2); |
| 470 EXPECT_EQ(NULL, view1_2->node()); | 495 EXPECT_EQ(NULL, view1_2->node()); |
| 471 } | 496 } |
| 472 | 497 |
| 473 // This test verifies that it is not possible to set the active view to a view | 498 // This test verifies that it is not possible to set the active view to a view |
| 474 // defined in a different connection. | 499 // defined in a different connection. |
| 475 // TODO(beng): write these tests for ViewTreeNode::AddChild(), RemoveChild() and | 500 // TODO(beng): write these tests for ViewTreeNode::AddChild(), RemoveChild() and |
| 476 // Contains(). | 501 // Contains(). |
| 477 TEST_F(ViewManagerTest, SetActiveViewAcrossConnection) { | 502 TEST_F(ViewManagerTest, SetActiveViewAcrossConnection) { |
| 478 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 503 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 479 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); | 504 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); |
| 480 | 505 |
| 481 View* view1_2 = View::Create(view_manager_2()); | 506 View* view1_2 = View::Create(view_manager_2()); |
| 482 EXPECT_DEATH(node1->SetActiveView(view1_2), ""); | 507 EXPECT_DEATH(node1->SetActiveView(view1_2), ""); |
| 483 } | 508 } |
| 484 | 509 |
| 510 // This test verifies that a node hierarchy constructed in one connection |
| 511 // becomes entirely visible to the second connection when the hierarchy is |
| 512 // attached. |
| 513 TEST_F(ViewManagerTest, MapSubtreeOnAttach) { |
| 514 ViewTreeNode* node1 = ViewTreeNode::Create(view_manager_1()); |
| 515 ViewTreeNode* node11 = CreateNodeInParent(node1); |
| 516 View* view11 = View::Create(view_manager_1()); |
| 517 node11->SetActiveView(view11); |
| 518 WaitForAllChangesToBeAcked(view_manager_1()); |
| 519 |
| 520 // Now attach this node tree to the root & wait for it to show up in the |
| 521 // second connection. |
| 522 view_manager_1()->tree()->AddChild(node1); |
| 523 WaitForTreeSizeToMatch(view_manager_2()->tree(), 3); |
| 524 |
| 525 ViewTreeNode* node11_2 = view_manager_2()->GetNodeById(node11->id()); |
| 526 View* view11_2 = view_manager_2()->GetViewById(view11->id()); |
| 527 EXPECT_TRUE(node11_2 != NULL); |
| 528 EXPECT_EQ(view11_2, node11_2->active_view()); |
| 529 } |
| 530 |
| 485 } // namespace view_manager | 531 } // namespace view_manager |
| 486 } // namespace mojo | 532 } // namespace mojo |
| OLD | NEW |