Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(481)

Side by Side Diff: mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc

Issue 272833002: View synchronization (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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"
11 #include "mojo/services/public/cpp/view_manager/view.h"
12 #include "mojo/services/public/cpp/view_manager/view_observer.h"
11 #include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h" 13 #include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h"
12 #include "mojo/shell/shell_test_helper.h" 14 #include "mojo/shell/shell_test_helper.h"
13 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
14 16
15 namespace mojo { 17 namespace mojo {
16 namespace services { 18 namespace services {
17 namespace view_manager { 19 namespace view_manager {
18 20
19 base::RunLoop* current_run_loop = NULL; 21 base::RunLoop* current_run_loop = NULL;
20 22
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 HierarchyChanged_NodeRemovedObserver observer(view_manager_2()); 240 HierarchyChanged_NodeRemovedObserver observer(view_manager_2());
239 241
240 view_manager_1()->tree()->RemoveChild(node1); 242 view_manager_1()->tree()->RemoveChild(node1);
241 DoRunLoop(); 243 DoRunLoop();
242 244
243 ViewTreeNode* tree2 = view_manager_2()->tree(); 245 ViewTreeNode* tree2 = view_manager_2()->tree();
244 246
245 EXPECT_TRUE(tree2->children().empty()); 247 EXPECT_TRUE(tree2->children().empty());
246 } 248 }
247 249
248 class NodeDestroyed_Waiter : public ViewTreeNodeObserver { 250 // Utility class that waits for the destruction of some number of nodes and
251 // views.
252 class DestructionWaiter : public ViewTreeNodeObserver,
253 public ViewObserver {
249 public: 254 public:
250 NodeDestroyed_Waiter(ViewManager* view_manager, TransportNodeId id) 255 // |nodes| or |views| can be NULL.
251 : id_(id), 256 DestructionWaiter(ViewManager* view_manager,
252 view_manager_(view_manager) { 257 std::set<TransportNodeId>* nodes,
253 view_manager_->GetNodeById(id)->AddObserver(this); 258 std::set<TransportViewId>* views)
259 : nodes_(nodes),
260 views_(views) {
261 DCHECK(nodes || views);
262 if (nodes) {
263 for (std::set<TransportNodeId>::const_iterator it = nodes->begin();
264 it != nodes->end(); ++it) {
265 view_manager->GetNodeById(*it)->AddObserver(this);
266 }
267 }
268 if (views) {
269 for (std::set<TransportViewId>::const_iterator it = views->begin();
270 it != views->end(); ++it) {
271 view_manager->GetViewById(*it)->AddObserver(this);
272 }
273 }
254 DoRunLoop(); 274 DoRunLoop();
255 } 275 }
256 virtual ~NodeDestroyed_Waiter() {
257 }
258 276
259 private: 277 private:
260 // Overridden from TreeObserverBase: 278 // Overridden from ViewTreeNodeObserver:
261 virtual void OnNodeDestroy(ViewTreeNode* node, 279 virtual void OnNodeDestroy(
262 DispositionChangePhase phase) OVERRIDE { 280 ViewTreeNode* node,
263 if (phase != DISPOSITION_CHANGED) 281 ViewTreeNodeObserver::DispositionChangePhase phase) OVERRIDE {
282 if (phase != ViewTreeNodeObserver::DISPOSITION_CHANGED)
264 return; 283 return;
265 if (node->id() == id_) 284 std::set<TransportNodeId>::const_iterator it = nodes_->find(node->id());
285 if (it != nodes_->end())
286 nodes_->erase(it);
287 if (CanQuit())
266 QuitRunLoop(); 288 QuitRunLoop();
267 } 289 }
268 290
269 TransportNodeId id_; 291 // Overridden from ViewObserver:
270 ViewManager* view_manager_; 292 virtual void OnViewDestroy(
293 View* view,
294 ViewObserver::DispositionChangePhase phase) OVERRIDE {
295 if (phase != ViewObserver::DISPOSITION_CHANGED)
296 return;
297 std::set<TransportViewId>::const_iterator it = views_->find(view->id());
298 if (it != views_->end())
299 views_->erase(it);
300 if (CanQuit())
301 QuitRunLoop();
302 }
271 303
272 DISALLOW_COPY_AND_ASSIGN(NodeDestroyed_Waiter); 304 bool CanQuit() {
305 return (!nodes_ || nodes_->empty()) && (!views_ || views_->empty());
306 }
307
308 std::set<TransportNodeId>* nodes_;
309 std::set<TransportViewId>* views_;
310
311 DISALLOW_COPY_AND_ASSIGN(DestructionWaiter);
273 }; 312 };
274 313
275 TEST_F(ViewManagerTest, NodeDestroyed) { 314 TEST_F(ViewManagerTest, NodeDestroyed) {
276 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); 315 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
277 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); 316 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
278 317
279 // |node1| will be deleted after calling Destroy() below. 318 // |node1| will be deleted after calling Destroy() below.
280 TransportNodeId id = node1->id(); 319 TransportNodeId id = node1->id();
281 node1->Destroy(); 320 node1->Destroy();
282 NodeDestroyed_Waiter destroyed_waiter(view_manager_2(), id); 321
322 std::set<TransportNodeId> nodes;
323 nodes.insert(id);
324 DestructionWaiter destroyed_waiter(view_manager_2(), &nodes, NULL);
283 325
284 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); 326 EXPECT_TRUE(view_manager_2()->tree()->children().empty());
327 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(id));
285 } 328 }
286 329
287 TEST_F(ViewManagerTest, ViewManagerDestroyed) { 330 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNode) {
288 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); 331 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
289 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); 332 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
290 333
291 TransportNodeId id = node1->id(); 334 TransportNodeId id = node1->id();
292 DestroyViewManager1(); 335 DestroyViewManager1();
293 NodeDestroyed_Waiter destroyed_waiter(view_manager_2(), id); 336 std::set<TransportNodeId> nodes;
337 nodes.insert(id);
338 DestructionWaiter destroyed_waiter(view_manager_2(), &nodes, NULL);
294 339
295 // tree() should still be valid, since it's owned by neither connection. 340 // tree() should still be valid, since it's owned by neither connection.
296 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); 341 EXPECT_TRUE(view_manager_2()->tree()->children().empty());
297 } 342 }
298 343
344 // Waits until the active view id of the supplied node changes.
345 class ActiveViewChangedWaiter : public ViewTreeNodeObserver {
346 public:
347 explicit ActiveViewChangedWaiter(ViewTreeNode* node)
348 : node_(node) {
349 node_->AddObserver(this);
350 DoRunLoop();
351 }
352 virtual ~ActiveViewChangedWaiter() {
353 node_->RemoveObserver(this);
354 }
355
356 private:
357 // Overridden from ViewTreeNodeObserver:
358 virtual void OnNodeActiveViewChange(ViewTreeNode* node,
359 View* old_view,
360 View* new_view,
361 DispositionChangePhase phase) OVERRIDE {
362 DCHECK_EQ(node, node_);
363 QuitRunLoop();
364 }
365
366 ViewTreeNode* node_;
367
368 DISALLOW_COPY_AND_ASSIGN(ActiveViewChangedWaiter);
369 };
370
371 TEST_F(ViewManagerTest, SetActiveView) {
372 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
373 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
374
375 View* view1 = View::Create(view_manager_1());
376 node1->SetActiveView(view1);
377
378 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id());
379 ActiveViewChangedWaiter waiter(node1_2);
380
381 EXPECT_EQ(node1_2->active_view()->id(), view1->id());
382 }
383
384 TEST_F(ViewManagerTest, DestroyView) {
385 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
386 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
387
388 View* view1 = View::Create(view_manager_1());
389 node1->SetActiveView(view1);
390
391 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id());
392 ActiveViewChangedWaiter active_view_waiter(node1_2);
393
394 TransportViewId view1_id = view1->id();
395 view1->Destroy();
396
397 std::set<TransportViewId> views;
398 views.insert(view1_id);
399 DestructionWaiter destruction_waiter(view_manager_2(), NULL, &views);
400 EXPECT_EQ(NULL, node1_2->active_view());
401 EXPECT_EQ(NULL, view_manager_2()->GetViewById(view1_id));
402 }
403
404 // Destroying the connection that created a node and view should result in that
405 // node and view disappearing from all connections that see them.
406 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNodeAndView) {
407 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
408 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
409
410 View* view1 = View::Create(view_manager_1());
411 node1->SetActiveView(view1);
412
413 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id());
414 {
415 ActiveViewChangedWaiter active_view_waiter(node1_2);
416 }
417
418 TransportNodeId node1_id = node1->id();
419 TransportViewId view1_id = view1->id();
420
421 DestroyViewManager1();
422 std::set<TransportNodeId> observed_nodes;
423 observed_nodes.insert(node1_id);
424 std::set<TransportViewId> observed_views;
425 observed_views.insert(view1_id);
426 DestructionWaiter destruction_waiter(view_manager_2(),
427 &observed_nodes,
428 &observed_views);
429
430 // tree() should still be valid, since it's owned by neither connection.
431 EXPECT_TRUE(view_manager_2()->tree()->children().empty());
432 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(node1_id));
433 EXPECT_EQ(NULL, view_manager_2()->GetViewById(view1_id));
434 }
435
436 // This test validates the following scenario:
437 // - a node originating from one connection
438 // - a view originating from a second connection
439 // + the connection originating the node is destroyed
440 // -> the view should still exist (since the second connection is live) but
441 // should be disconnected from any nodes.
442 TEST_F(ViewManagerTest,
443 ViewManagerDestroyed_CleanupNodeAndViewFromDifferentConnections) {
444 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
445 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
446
447 View* view1_2 = View::Create(view_manager_2());
448 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id());
449 node1_2->SetActiveView(view1_2);
450
451 {
452 ActiveViewChangedWaiter active_view_waiter(node1);
453 }
454
455 TransportNodeId node1_id = node1->id();
456 TransportViewId view1_2_id = view1_2->id();
457
458 DestroyViewManager1();
459 std::set<TransportNodeId> nodes;
460 nodes.insert(node1_id);
461 DestructionWaiter destruction_waiter(view_manager_2(), &nodes, NULL);
462
463 // tree() should still be valid, since it's owned by neither connection.
464 EXPECT_TRUE(view_manager_2()->tree()->children().empty());
465 // node1 was owned by the first connection, so it should be gone.
466 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(node1_id));
467 // view1_2 was owned by the second connection, so it should still exist, but
468 // disconnected from the node tree.
469 View* another_view1_2 = view_manager_2()->GetViewById(view1_2_id);
470 EXPECT_EQ(view1_2, another_view1_2);
471 EXPECT_EQ(NULL, view1_2->node());
472 }
473
474 // This test verifies that it is not possible to set the active view to a view
475 // defined in a different connection.
476 // TODO(beng): write these tests for ViewTreeNode::AddChild(), RemoveChild() and
477 // Contains().
478 TEST_F(ViewManagerTest, SetActiveViewAcrossConnection) {
479 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
480 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
481
482 View* view1_2 = View::Create(view_manager_2());
483 EXPECT_DEATH(node1->SetActiveView(view1_2), "");
484 }
485
299 } // namespace view_manager 486 } // namespace view_manager
300 } // namespace services 487 } // namespace services
301 } // namespace mojo 488 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h ('k') | mojo/services/public/cpp/view_manager/view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698