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)); | |
sky
2014/05/16 23:28:22
nit: indent 2 more.
| |
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 |