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

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), views_(views) {
sky 2014/05/12 21:17:58 nit: wrap views_ to newline
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 }
254 DoRunLoop(); 273 DoRunLoop();
255 } 274 }
256 virtual ~NodeDestroyed_Waiter() {
257 }
258 275
259 private: 276 private:
260 // Overridden from TreeObserverBase: 277 // Overridden from ViewTreeNodeObserver:
261 virtual void OnNodeDestroy(ViewTreeNode* node, 278 virtual void OnNodeDestroy(
262 DispositionChangePhase phase) OVERRIDE { 279 ViewTreeNode* node,
263 if (phase != DISPOSITION_CHANGED) 280 ViewTreeNodeObserver::DispositionChangePhase phase) OVERRIDE {
281 if (phase != ViewTreeNodeObserver::DISPOSITION_CHANGED)
264 return; 282 return;
265 if (node->id() == id_) 283 std::set<TransportNodeId>::const_iterator it = nodes_->find(node->id());
284 if (it != nodes_->end())
285 nodes_->erase(it);
286 if (CanQuit())
266 QuitRunLoop(); 287 QuitRunLoop();
267 } 288 }
268 289
269 TransportNodeId id_; 290 // Overridden from ViewObserver:
270 ViewManager* view_manager_; 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 }
271 302
272 DISALLOW_COPY_AND_ASSIGN(NodeDestroyed_Waiter); 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);
273 }; 311 };
274 312
275 TEST_F(ViewManagerTest, NodeDestroyed) { 313 TEST_F(ViewManagerTest, NodeDestroyed) {
276 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); 314 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
277 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); 315 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
278 316
279 // |node1| will be deleted after calling Destroy() below. 317 // |node1| will be deleted after calling Destroy() below.
280 TransportNodeId id = node1->id(); 318 TransportNodeId id = node1->id();
281 node1->Destroy(); 319 node1->Destroy();
282 NodeDestroyed_Waiter destroyed_waiter(view_manager_2(), id); 320
321 std::set<TransportNodeId> nodes;
322 nodes.insert(id);
323 DestructionWaiter destroyed_waiter(view_manager_2(), &nodes, NULL);
283 324
284 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); 325 EXPECT_TRUE(view_manager_2()->tree()->children().empty());
326 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(id));
285 } 327 }
286 328
287 TEST_F(ViewManagerTest, ViewManagerDestroyed) { 329 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNode) {
288 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); 330 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
289 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2); 331 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
290 332
291 TransportNodeId id = node1->id(); 333 TransportNodeId id = node1->id();
292 DestroyViewManager1(); 334 DestroyViewManager1();
293 NodeDestroyed_Waiter destroyed_waiter(view_manager_2(), id); 335 std::set<TransportNodeId> nodes;
336 nodes.insert(id);
337 DestructionWaiter destroyed_waiter(view_manager_2(), &nodes, NULL);
294 338
295 // tree() should still be valid, since it's owned by neither connection. 339 // tree() should still be valid, since it's owned by neither connection.
296 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); 340 EXPECT_TRUE(view_manager_2()->tree()->children().empty());
297 } 341 }
298 342
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) {
371 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
372 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
373
374 View* view1 = View::Create(view_manager_1());
375 node1->SetActiveView(view1);
376
377 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id());
378 ActiveViewChangedWaiter waiter(node1_2);
379
380 EXPECT_EQ(node1_2->active_view()->id(), view1->id());
381 }
382
383 TEST_F(ViewManagerTest, DestroyView) {
384 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
385 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
386
387 View* view1 = View::Create(view_manager_1());
388 node1->SetActiveView(view1);
389
390 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id());
391 ActiveViewChangedWaiter active_view_waiter(node1_2);
392
393 TransportViewId view1_id = view1->id();
394 view1->Destroy();
395
396 std::set<TransportViewId> views;
397 views.insert(view1_id);
398 DestructionWaiter destruction_waiter(view_manager_2(), NULL, &views);
399 EXPECT_EQ(NULL, node1_2->active_view());
400 EXPECT_EQ(NULL, view_manager_2()->GetViewById(view1_id));
401 }
402
403 // Destroying the connection that created a node and view should result in that
404 // node and view disappearing from all connections that see them.
405 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNodeAndView) {
406 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
407 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
408
409 View* view1 = View::Create(view_manager_1());
410 node1->SetActiveView(view1);
411
412 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id());
413 {
414 ActiveViewChangedWaiter active_view_waiter(node1_2);
415 }
416
417 TransportNodeId node1_id = node1->id();
418 TransportViewId view1_id = view1->id();
419
420 DestroyViewManager1();
421 std::set<TransportNodeId> observed_nodes;
422 observed_nodes.insert(node1_id);
423 std::set<TransportViewId> observed_views;
424 observed_views.insert(view1_id);
425 DestructionWaiter destruction_waiter(view_manager_2(),
426 &observed_nodes,
427 &observed_views);
428
429 // tree() should still be valid, since it's owned by neither connection.
430 EXPECT_TRUE(view_manager_2()->tree()->children().empty());
431 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(node1_id));
432 EXPECT_EQ(NULL, view_manager_2()->GetViewById(view1_id));
433 }
434
435 // This test validates the following scenario:
436 // - a node originating from one connection
437 // - a view originating from a second connection
438 // + the connection originating the node is destroyed
439 // -> the view should still exist (since the second connection is live) but
440 // should be disconnected from any nodes.
441 TEST_F(ViewManagerTest,
442 ViewManagerDestroyed_CleanupNodeAndViewFromDifferentConnections) {
443 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
444 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
445
446 View* view1_2 = View::Create(view_manager_2());
447 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id());
448 node1_2->SetActiveView(view1_2);
449
450 {
451 ActiveViewChangedWaiter active_view_waiter(node1);
452 }
453
454 TransportNodeId node1_id = node1->id();
455 TransportViewId view1_2_id = view1_2->id();
456
457 DestroyViewManager1();
458 std::set<TransportNodeId> nodes;
459 nodes.insert(node1_id);
460 DestructionWaiter destruction_waiter(view_manager_2(), &nodes, NULL);
461
462 // tree() should still be valid, since it's owned by neither connection.
463 EXPECT_TRUE(view_manager_2()->tree()->children().empty());
464 // node1 was owned by the first connection, so it should be gone.
465 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(node1_id));
466 // view1_2 was owned by the second connection, so it should still exist, but
467 // disconnected from the node tree.
468 View* another_view1_2 = view_manager_2()->GetViewById(view1_2_id);
469 EXPECT_EQ(view1_2, another_view1_2);
470 EXPECT_EQ(NULL, view1_2->node());
471 }
472
473 // This test verifies that it is not possible to set the active view to a view
474 // defined in a different connection.
475 // TODO(beng): write these tests for ViewTreeNode::AddChild(), RemoveChild() and
476 // Contains().
477 TEST_F(ViewManagerTest, SetActiveViewAcrossConnection) {
478 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree());
479 TreeSizeMatchesWaiter init_waiter(view_manager_2(), 2);
480
481 View* view1_2 = View::Create(view_manager_2());
482 EXPECT_DEATH(node1->SetActiveView(view1_2), "");
483 }
484
299 } // namespace view_manager 485 } // namespace view_manager
300 } // namespace services 486 } // namespace services
301 } // namespace mojo 487 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698