| 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_tree_node_private.h" | 9 #include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h" |
| 10 #include "mojo/services/public/cpp/view_manager/util.h" | 10 #include "mojo/services/public/cpp/view_manager/util.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 current_run_loop->Run(); | 24 current_run_loop->Run(); |
| 25 current_run_loop = NULL; | 25 current_run_loop = NULL; |
| 26 } | 26 } |
| 27 | 27 |
| 28 void QuitRunLoop() { | 28 void QuitRunLoop() { |
| 29 current_run_loop->Quit(); | 29 current_run_loop->Quit(); |
| 30 } | 30 } |
| 31 | 31 |
| 32 // ViewManager ----------------------------------------------------------------- | 32 // ViewManager ----------------------------------------------------------------- |
| 33 | 33 |
| 34 // These tests model synchronization of two peer connections to the view manager |
| 35 // service, that are given access to some root node. |
| 36 |
| 34 class ViewManagerTest : public testing::Test { | 37 class ViewManagerTest : public testing::Test { |
| 35 public: | 38 public: |
| 36 ViewManagerTest() : commit_count_(0) {} | 39 ViewManagerTest() : commit_count_(0) {} |
| 37 | 40 |
| 38 protected: | 41 protected: |
| 39 ViewManager* view_manager_1() { return view_manager_1_.get(); } | 42 ViewManager* view_manager_1() { return view_manager_1_.get(); } |
| 40 ViewManager* view_manager_2() { return view_manager_2_.get(); } | 43 ViewManager* view_manager_2() { return view_manager_2_.get(); } |
| 41 | 44 |
| 42 scoped_ptr<ViewTreeNode> CreateNodeInParent(ViewTreeNode* parent) { | 45 ViewTreeNode* CreateNodeInParent(ViewTreeNode* parent) { |
| 43 ViewManager* parent_manager = ViewTreeNodePrivate(parent).view_manager(); | 46 ViewManager* parent_manager = ViewTreeNodePrivate(parent).view_manager(); |
| 44 scoped_ptr<ViewTreeNode> node(new ViewTreeNode(parent_manager)); | 47 ViewTreeNode* node = ViewTreeNode::Create(parent_manager); |
| 45 parent->AddChild(node.get()); | 48 parent->AddChild(node); |
| 46 return node.Pass(); | 49 return node; |
| 50 } |
| 51 |
| 52 void DestroyViewManager1() { |
| 53 view_manager_1_.reset(); |
| 47 } | 54 } |
| 48 | 55 |
| 49 private: | 56 private: |
| 50 // Overridden from testing::Test: | 57 // Overridden from testing::Test: |
| 51 virtual void SetUp() OVERRIDE { | 58 virtual void SetUp() OVERRIDE { |
| 52 test_helper_.Init(); | 59 test_helper_.Init(); |
| 53 view_manager_1_.reset(new ViewManager(test_helper_.shell())); | 60 view_manager_1_.reset(new ViewManager(test_helper_.shell())); |
| 54 view_manager_2_.reset(new ViewManager(test_helper_.shell())); | 61 view_manager_2_.reset(new ViewManager(test_helper_.shell())); |
| 55 view_manager_1_->Init(); | 62 view_manager_1_->Init(); |
| 56 view_manager_2_->Init(); | 63 view_manager_2_->Init(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 78 } | 85 } |
| 79 | 86 |
| 80 protected: | 87 protected: |
| 81 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) = 0; | 88 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) = 0; |
| 82 | 89 |
| 83 ViewManager* view_manager() { return view_manager_; } | 90 ViewManager* view_manager() { return view_manager_; } |
| 84 | 91 |
| 85 private: | 92 private: |
| 86 // Overridden from ViewTreeNodeObserver: | 93 // Overridden from ViewTreeNodeObserver: |
| 87 virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE { | 94 virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE { |
| 88 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) | |
| 89 return; | |
| 90 if (ShouldQuitRunLoop(params)) | 95 if (ShouldQuitRunLoop(params)) |
| 91 QuitRunLoop(); | 96 QuitRunLoop(); |
| 92 } | 97 } |
| 93 | 98 |
| 94 ViewManager* view_manager_; | 99 ViewManager* view_manager_; |
| 95 DISALLOW_COPY_AND_ASSIGN(TreeObserverBase); | 100 DISALLOW_COPY_AND_ASSIGN(TreeObserverBase); |
| 96 }; | 101 }; |
| 97 | 102 |
| 98 // Spins a runloop until the tree beginning at |root| has |tree_size| nodes | 103 // Spins a runloop until the tree beginning at |root| has |tree_size| nodes |
| 99 // (including |root|). | 104 // (including |root|). |
| 100 class TreeSizeMatchesWaiter : public TreeObserverBase { | 105 class TreeSizeMatchesWaiter : public TreeObserverBase { |
| 101 public: | 106 public: |
| 102 TreeSizeMatchesWaiter(ViewManager* view_manager, size_t tree_size) | 107 TreeSizeMatchesWaiter(ViewManager* view_manager, size_t tree_size) |
| 103 : TreeObserverBase(view_manager), | 108 : TreeObserverBase(view_manager), |
| 104 tree_size_(tree_size) { | 109 tree_size_(tree_size) { |
| 105 DoRunLoop(); | 110 DoRunLoop(); |
| 106 } | 111 } |
| 107 virtual ~TreeSizeMatchesWaiter() {} | 112 virtual ~TreeSizeMatchesWaiter() {} |
| 108 | 113 |
| 109 private: | 114 private: |
| 110 // Overridden from TreeObserverBase: | 115 // Overridden from TreeObserverBase: |
| 111 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { | 116 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { |
| 117 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) |
| 118 return false; |
| 112 return CountNodes(view_manager()->tree()) == tree_size_; | 119 return CountNodes(view_manager()->tree()) == tree_size_; |
| 113 } | 120 } |
| 114 | 121 |
| 115 size_t CountNodes(ViewTreeNode* node) const { | 122 size_t CountNodes(ViewTreeNode* node) const { |
| 116 size_t count = 1; | 123 size_t count = 1; |
| 117 ViewTreeNode::Children::const_iterator it = node->children().begin(); | 124 ViewTreeNode::Children::const_iterator it = node->children().begin(); |
| 118 for (; it != node->children().end(); ++it) | 125 for (; it != node->children().end(); ++it) |
| 119 count += CountNodes(*it); | 126 count += CountNodes(*it); |
| 120 return count; | 127 return count; |
| 121 } | 128 } |
| 122 | 129 |
| 123 size_t tree_size_; | 130 size_t tree_size_; |
| 124 DISALLOW_COPY_AND_ASSIGN(TreeSizeMatchesWaiter); | 131 DISALLOW_COPY_AND_ASSIGN(TreeSizeMatchesWaiter); |
| 125 }; | 132 }; |
| 126 | 133 |
| 127 | 134 |
| 128 class HierarchyChanged_NodeCreatedObserver : public TreeObserverBase { | 135 class HierarchyChanged_NodeCreatedObserver : public TreeObserverBase { |
| 129 public: | 136 public: |
| 130 explicit HierarchyChanged_NodeCreatedObserver(ViewManager* view_manager) | 137 explicit HierarchyChanged_NodeCreatedObserver(ViewManager* view_manager) |
| 131 : TreeObserverBase(view_manager) {} | 138 : TreeObserverBase(view_manager) {} |
| 132 virtual ~HierarchyChanged_NodeCreatedObserver() {} | 139 virtual ~HierarchyChanged_NodeCreatedObserver() {} |
| 133 | 140 |
| 134 private: | 141 private: |
| 135 // Overridden from TreeObserverBase: | 142 // Overridden from TreeObserverBase: |
| 136 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { | 143 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { |
| 144 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) |
| 145 return false; |
| 137 return params.receiver == view_manager()->tree() && | 146 return params.receiver == view_manager()->tree() && |
| 138 !params.old_parent && | 147 !params.old_parent && |
| 139 params.new_parent == view_manager()->tree(); | 148 params.new_parent == view_manager()->tree(); |
| 140 } | 149 } |
| 141 | 150 |
| 142 DISALLOW_COPY_AND_ASSIGN(HierarchyChanged_NodeCreatedObserver); | 151 DISALLOW_COPY_AND_ASSIGN(HierarchyChanged_NodeCreatedObserver); |
| 143 }; | 152 }; |
| 144 | 153 |
| 145 TEST_F(ViewManagerTest, HierarchyChanged_NodeCreated) { | 154 TEST_F(ViewManagerTest, HierarchyChanged_NodeCreated) { |
| 146 HierarchyChanged_NodeCreatedObserver observer(view_manager_2()); | 155 HierarchyChanged_NodeCreatedObserver observer(view_manager_2()); |
| 147 scoped_ptr<ViewTreeNode> node1(new ViewTreeNode(view_manager_1())); | 156 ViewTreeNode* node1 = ViewTreeNode::Create(view_manager_1()); |
| 148 view_manager_1()->tree()->AddChild(node1.get()); | 157 view_manager_1()->tree()->AddChild(node1); |
| 149 DoRunLoop(); | 158 DoRunLoop(); |
| 150 | 159 |
| 151 EXPECT_EQ(view_manager_2()->tree()->children().front()->id(), node1->id()); | 160 EXPECT_EQ(view_manager_2()->tree()->children().front()->id(), node1->id()); |
| 152 } | 161 } |
| 153 | 162 |
| 154 // Quits the current runloop when the root is notified about a node moved from | 163 // Quits the current runloop when the root is notified about a node moved from |
| 155 // |old_parent_id| to |new_parent_id|. | 164 // |old_parent_id| to |new_parent_id|. |
| 156 class HierarchyChanged_NodeMovedObserver : public TreeObserverBase { | 165 class HierarchyChanged_NodeMovedObserver : public TreeObserverBase { |
| 157 public: | 166 public: |
| 158 HierarchyChanged_NodeMovedObserver(ViewManager* view_manager, | 167 HierarchyChanged_NodeMovedObserver(ViewManager* view_manager, |
| 159 TransportNodeId old_parent_id, | 168 TransportNodeId old_parent_id, |
| 160 TransportNodeId new_parent_id) | 169 TransportNodeId new_parent_id) |
| 161 : TreeObserverBase(view_manager), | 170 : TreeObserverBase(view_manager), |
| 162 old_parent_id_(old_parent_id), | 171 old_parent_id_(old_parent_id), |
| 163 new_parent_id_(new_parent_id) {} | 172 new_parent_id_(new_parent_id) {} |
| 164 virtual ~HierarchyChanged_NodeMovedObserver() {} | 173 virtual ~HierarchyChanged_NodeMovedObserver() {} |
| 165 | 174 |
| 166 private: | 175 private: |
| 167 // Overridden from TreeObserverBase: | 176 // Overridden from TreeObserverBase: |
| 168 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { | 177 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { |
| 178 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) |
| 179 return false; |
| 169 return params.receiver == view_manager()->tree() && | 180 return params.receiver == view_manager()->tree() && |
| 170 params.old_parent->id() == old_parent_id_&& | 181 params.old_parent->id() == old_parent_id_&& |
| 171 params.new_parent->id() == new_parent_id_; | 182 params.new_parent->id() == new_parent_id_; |
| 172 } | 183 } |
| 173 | 184 |
| 174 TransportNodeId old_parent_id_; | 185 TransportNodeId old_parent_id_; |
| 175 TransportNodeId new_parent_id_; | 186 TransportNodeId new_parent_id_; |
| 176 | 187 |
| 177 DISALLOW_COPY_AND_ASSIGN(HierarchyChanged_NodeMovedObserver); | 188 DISALLOW_COPY_AND_ASSIGN(HierarchyChanged_NodeMovedObserver); |
| 178 }; | 189 }; |
| 179 | 190 |
| 180 TEST_F(ViewManagerTest, HierarchyChanged_NodeMoved) { | 191 TEST_F(ViewManagerTest, HierarchyChanged_NodeMoved) { |
| 181 scoped_ptr<ViewTreeNode> node1(CreateNodeInParent(view_manager_1()->tree())); | 192 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 182 scoped_ptr<ViewTreeNode> node2(CreateNodeInParent(view_manager_1()->tree())); | 193 ViewTreeNode* node2 = CreateNodeInParent(view_manager_1()->tree()); |
| 183 scoped_ptr<ViewTreeNode> node21(CreateNodeInParent(node2.get())); | 194 ViewTreeNode* node21 = CreateNodeInParent(node2); |
| 184 TreeSizeMatchesWaiter waiter(view_manager_2(), 4); | 195 TreeSizeMatchesWaiter waiter(view_manager_2(), 4); |
| 185 | 196 |
| 186 HierarchyChanged_NodeMovedObserver observer(view_manager_2(), | 197 HierarchyChanged_NodeMovedObserver observer(view_manager_2(), |
| 187 node2->id(), | 198 node2->id(), |
| 188 node1->id()); | 199 node1->id()); |
| 189 | 200 |
| 190 node1->AddChild(node21.get()); | 201 node1->AddChild(node21); |
| 191 DoRunLoop(); | 202 DoRunLoop(); |
| 192 | 203 |
| 193 ViewTreeNode* tree2 = view_manager_2()->tree(); | 204 ViewTreeNode* tree2 = view_manager_2()->tree(); |
| 194 | 205 |
| 195 EXPECT_EQ(tree2->children().size(), 2u); | 206 EXPECT_EQ(tree2->children().size(), 2u); |
| 196 ViewTreeNode* tree2_node1 = tree2->GetChildById(node1->id()); | 207 ViewTreeNode* tree2_node1 = tree2->GetChildById(node1->id()); |
| 197 EXPECT_EQ(tree2_node1->children().size(), 1u); | 208 EXPECT_EQ(tree2_node1->children().size(), 1u); |
| 198 ViewTreeNode* tree2_node2 = tree2->GetChildById(node2->id()); | 209 ViewTreeNode* tree2_node2 = tree2->GetChildById(node2->id()); |
| 199 EXPECT_TRUE(tree2_node2->children().empty()); | 210 EXPECT_TRUE(tree2_node2->children().empty()); |
| 200 ViewTreeNode* tree2_node21 = tree2->GetChildById(node21->id()); | 211 ViewTreeNode* tree2_node21 = tree2->GetChildById(node21->id()); |
| 201 EXPECT_EQ(tree2_node21->parent(), tree2_node1); | 212 EXPECT_EQ(tree2_node21->parent(), tree2_node1); |
| 202 } | 213 } |
| 203 | 214 |
| 204 // TODO(beng): node destruction | 215 class HierarchyChanged_NodeRemovedObserver : public TreeObserverBase { |
| 216 public: |
| 217 HierarchyChanged_NodeRemovedObserver(ViewManager* view_manager) |
| 218 : TreeObserverBase(view_manager) {} |
| 219 virtual ~HierarchyChanged_NodeRemovedObserver() {} |
| 220 |
| 221 private: |
| 222 // Overridden from TreeObserverBase: |
| 223 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { |
| 224 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGING) |
| 225 return false; |
| 226 return params.receiver == view_manager()->tree() && |
| 227 params.old_parent->id() == params.receiver->id() && |
| 228 params.new_parent == 0; |
| 229 } |
| 230 |
| 231 DISALLOW_COPY_AND_ASSIGN(HierarchyChanged_NodeRemovedObserver); |
| 232 }; |
| 233 |
| 234 TEST_F(ViewManagerTest, HierarchyChanged_NodeRemoved) { |
| 235 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 236 TreeSizeMatchesWaiter waiter(view_manager_2(), 2); |
| 237 |
| 238 HierarchyChanged_NodeRemovedObserver observer(view_manager_2()); |
| 239 |
| 240 view_manager_1()->tree()->RemoveChild(node1); |
| 241 DoRunLoop(); |
| 242 |
| 243 ViewTreeNode* tree2 = view_manager_2()->tree(); |
| 244 |
| 245 EXPECT_TRUE(tree2->children().empty()); |
| 246 } |
| 247 |
| 248 class NodeDestroyed_Waiter : public ViewTreeNodeObserver { |
| 249 public: |
| 250 NodeDestroyed_Waiter(ViewManager* view_manager, TransportNodeId id) |
| 251 : view_manager_(view_manager), |
| 252 id_(id) { |
| 253 view_manager_->GetNodeById(id)->AddObserver(this); |
| 254 DoRunLoop(); |
| 255 } |
| 256 virtual ~NodeDestroyed_Waiter() { |
| 257 } |
| 258 |
| 259 private: |
| 260 // Overridden from TreeObserverBase: |
| 261 virtual void OnNodeDestroy(ViewTreeNode* node, |
| 262 DispositionChangePhase phase) OVERRIDE { |
| 263 if (phase != DISPOSITION_CHANGED) |
| 264 return; |
| 265 if (node->id() == id_) |
| 266 QuitRunLoop(); |
| 267 } |
| 268 |
| 269 TransportNodeId id_; |
| 270 ViewManager* view_manager_; |
| 271 |
| 272 DISALLOW_COPY_AND_ASSIGN(NodeDestroyed_Waiter); |
| 273 }; |
| 274 |
| 275 TEST_F(ViewManagerTest, NodeDestroyed) { |
| 276 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 277 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); |
| 278 |
| 279 // |node1| will be deleted after calling Destroy() below. |
| 280 TransportNodeId id = node1->id(); |
| 281 node1->Destroy(); |
| 282 NodeDestroyed_Waiter destroyed_waiter(view_manager_2(), id); |
| 283 |
| 284 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); |
| 285 } |
| 286 |
| 287 TEST_F(ViewManagerTest, ViewManagerDestroyed) { |
| 288 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 289 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); |
| 290 |
| 291 TransportNodeId id = node1->id(); |
| 292 DestroyViewManager1(); |
| 293 NodeDestroyed_Waiter destroyed_waiter(view_manager_2(), id); |
| 294 |
| 295 // tree() should still be valid, since it's owned by neither connection. |
| 296 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); |
| 297 } |
| 205 | 298 |
| 206 } // namespace view_manager | 299 } // namespace view_manager |
| 207 } // namespace services | 300 } // namespace services |
| 208 } // namespace mojo | 301 } // namespace mojo |
| OLD | NEW |