Commit 3b149b73 authored by ben@chromium.org's avatar ben@chromium.org

Fix destruction tests.

I had to find a way to destroy a ViewManagerConnection from the client lib.
In the new world, the ViewManagerSynchronizer is the InterfaceImpl, and lifetime of all other client objects hangs off it.
ViewManagerSynchronizer is owned by the ServiceConnector which is owned by the Application object, so I had to find a way to delete that. In the test, I simply reset the ServiceLoader by URL. This tears down the synchronizer & corresponding ViewManagerConnection, triggering the correct notifications.

Dave, I had to add a NULL check in the service manager code because it hadn't considered there could be a NULL loader for a URL. LMK if you have a different idea.

R=davemoore@chromium.org, sky@chromium.org
http://crbug.com/365012

Review URL: https://codereview.chromium.org/315863002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274841 0039d316-1c4b-4281-b951-d872f2087c98
parent a1de169a
...@@ -185,7 +185,9 @@ void ServiceManager::OnServiceFactoryError(ServiceFactory* service_factory) { ...@@ -185,7 +185,9 @@ void ServiceManager::OnServiceFactoryError(ServiceFactory* service_factory) {
DCHECK(it != url_to_service_factory_.end()); DCHECK(it != url_to_service_factory_.end());
delete it->second; delete it->second;
url_to_service_factory_.erase(it); url_to_service_factory_.erase(it);
GetLoaderForURL(url)->OnServiceError(this, url); ServiceLoader* loader = GetLoaderForURL(url);
if (loader)
loader->OnServiceError(this, url);
} }
} // namespace mojo } // namespace mojo
...@@ -604,8 +604,11 @@ void ViewManagerSynchronizer::OnNodeDeleted(uint32_t node_id, ...@@ -604,8 +604,11 @@ void ViewManagerSynchronizer::OnNodeDeleted(uint32_t node_id,
next_server_change_id_ = server_change_id + 1; next_server_change_id_ = server_change_id + 1;
ViewTreeNode* node = view_manager()->GetNodeById(node_id); ViewTreeNode* node = view_manager()->GetNodeById(node_id);
if (node) if (node) {
if (view_manager()->tree() == node)
ViewManagerPrivate(view_manager()).set_root(NULL);
ViewTreeNodePrivate(node).LocalDestroy(); ViewTreeNodePrivate(node).LocalDestroy();
}
} }
void ViewManagerSynchronizer::OnNodeViewReplaced(uint32_t node_id, void ViewManagerSynchronizer::OnNodeViewReplaced(uint32_t node_id,
......
...@@ -50,15 +50,14 @@ void WaitForAllChangesToBeAcked(ViewManager* manager) { ...@@ -50,15 +50,14 @@ void WaitForAllChangesToBeAcked(ViewManager* manager) {
ViewManagerPrivate(manager).synchronizer()->ClearChangesAckedCallback(); ViewManagerPrivate(manager).synchronizer()->ClearChangesAckedCallback();
} }
// Used with IViewManager::Connect(). Creates a TestViewManagerClientConnection,
// which creates and owns the ViewManagerProxy.
class ConnectServiceLoader : public ServiceLoader { class ConnectServiceLoader : public ServiceLoader {
public: public:
explicit ConnectServiceLoader(base::Callback<void(ViewManager*)> callback) explicit ConnectServiceLoader(base::Callback<void(ViewManager*)> callback)
: callback_(callback) {} : callback_(callback) {}
virtual ~ConnectServiceLoader() {} virtual ~ConnectServiceLoader() {}
// ServiceLoader: private:
// Overridden from ServiceLoader:
virtual void LoadService(ServiceManager* manager, virtual void LoadService(ServiceManager* manager,
const GURL& url, const GURL& url,
ScopedMessagePipeHandle shell_handle) OVERRIDE { ScopedMessagePipeHandle shell_handle) OVERRIDE {
...@@ -70,7 +69,6 @@ class ConnectServiceLoader : public ServiceLoader { ...@@ -70,7 +69,6 @@ class ConnectServiceLoader : public ServiceLoader {
const GURL& url) OVERRIDE { const GURL& url) OVERRIDE {
} }
private:
ScopedVector<Application> apps_; ScopedVector<Application> apps_;
base::Callback<void(ViewManager*)> callback_; base::Callback<void(ViewManager*)> callback_;
...@@ -322,6 +320,10 @@ class ViewManagerTest : public testing::Test { ...@@ -322,6 +320,10 @@ class ViewManagerTest : public testing::Test {
return view_manager; return view_manager;
} }
void UnloadApplication(const GURL& url) {
test_helper_.SetLoaderForURL(scoped_ptr<ServiceLoader>(), url);
}
private: private:
// Overridden from testing::Test: // Overridden from testing::Test:
virtual void SetUp() OVERRIDE { virtual void SetUp() OVERRIDE {
...@@ -476,19 +478,20 @@ TEST_F(ViewManagerTest, NodeDestroyed) { ...@@ -476,19 +478,20 @@ TEST_F(ViewManagerTest, NodeDestroyed) {
EXPECT_EQ(NULL, embedded->GetNodeById(id)); EXPECT_EQ(NULL, embedded->GetNodeById(id));
} }
// TODO(beng): provide a way to terminate an application. TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNode) {
TEST_F(ViewManagerTest, DISABLED_ViewManagerDestroyed_CleanupNode) { ViewTreeNode* node = ViewTreeNode::Create(window_manager());
ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); window_manager()->tree()->AddChild(node);
WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); ViewManager* embedded = Embed(window_manager(), node);
TransportNodeId node_id = node->id();
UnloadApplication(GURL(kTestServiceURL));
TransportNodeId id = node1->id();
DestroyViewManager1();
std::set<TransportNodeId> nodes; std::set<TransportNodeId> nodes;
nodes.insert(id); nodes.insert(node_id);
WaitForDestruction(view_manager_2(), &nodes, NULL); WaitForDestruction(embedded, &nodes, NULL);
// tree() should still be valid, since it's owned by neither connection. EXPECT_EQ(NULL, embedded->tree());
EXPECT_TRUE(view_manager_2()->tree()->children().empty());
} }
TEST_F(ViewManagerTest, SetActiveView) { TEST_F(ViewManagerTest, SetActiveView) {
...@@ -530,30 +533,27 @@ TEST_F(ViewManagerTest, DestroyView) { ...@@ -530,30 +533,27 @@ TEST_F(ViewManagerTest, DestroyView) {
// Destroying the connection that created a node and view should result in that // Destroying the connection that created a node and view should result in that
// node and view disappearing from all connections that see them. // node and view disappearing from all connections that see them.
TEST_F(ViewManagerTest, DISABLED_ViewManagerDestroyed_CleanupNodeAndView) { TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNodeAndView) {
ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); ViewTreeNode* node = ViewTreeNode::Create(window_manager());
WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); window_manager()->tree()->AddChild(node);
View* view = View::Create(window_manager());
View* view1 = View::Create(view_manager_1()); node->SetActiveView(view);
node1->SetActiveView(view1); ViewManager* embedded = Embed(window_manager(), node);
ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); TransportNodeId node_id = node->id();
WaitForActiveViewToChange(node1_2); TransportViewId view_id = view->id();
TransportNodeId node1_id = node1->id(); UnloadApplication(GURL(kTestServiceURL));
TransportViewId view1_id = view1->id();
DestroyViewManager1();
std::set<TransportNodeId> observed_nodes; std::set<TransportNodeId> observed_nodes;
observed_nodes.insert(node1_id); observed_nodes.insert(node_id);
std::set<TransportViewId> observed_views; std::set<TransportViewId> observed_views;
observed_views.insert(view1_id); observed_views.insert(view_id);
WaitForDestruction(view_manager_2(), &observed_nodes, &observed_views); WaitForDestruction(embedded, &observed_nodes, &observed_views);
// tree() should still be valid, since it's owned by neither connection. EXPECT_EQ(NULL, embedded->tree());
EXPECT_TRUE(view_manager_2()->tree()->children().empty()); EXPECT_EQ(NULL, embedded->GetNodeById(node_id));
EXPECT_EQ(NULL, view_manager_2()->GetNodeById(node1_id)); EXPECT_EQ(NULL, embedded->GetViewById(view_id));
EXPECT_EQ(NULL, view_manager_2()->GetViewById(view1_id));
} }
// This test validates the following scenario: // This test validates the following scenario:
...@@ -563,32 +563,31 @@ TEST_F(ViewManagerTest, DISABLED_ViewManagerDestroyed_CleanupNodeAndView) { ...@@ -563,32 +563,31 @@ TEST_F(ViewManagerTest, DISABLED_ViewManagerDestroyed_CleanupNodeAndView) {
// -> the view should still exist (since the second connection is live) but // -> the view should still exist (since the second connection is live) but
// should be disconnected from any nodes. // should be disconnected from any nodes.
TEST_F(ViewManagerTest, TEST_F(ViewManagerTest,
DISABLED_ViewManagerDestroyed_CleanupNodeAndViewFromDifferentConnections) { ViewManagerDestroyed_CleanupNodeAndViewFromDifferentConnections) {
ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); ViewTreeNode* node = ViewTreeNode::Create(window_manager());
WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); window_manager()->tree()->AddChild(node);
ViewManager* embedded = Embed(window_manager(), node);
View* view_in_embedded = View::Create(embedded);
ViewTreeNode* node_in_embedded = embedded->GetNodeById(node->id());
node_in_embedded->SetActiveView(view_in_embedded);
View* view1_2 = View::Create(view_manager_2()); WaitForActiveViewToChange(node);
ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id());
node1_2->SetActiveView(view1_2);
WaitForActiveViewToChange(node1);
TransportNodeId node1_id = node1->id(); TransportNodeId node_id = node->id();
TransportViewId view1_2_id = view1_2->id(); TransportViewId view_id = view_in_embedded->id();
DestroyViewManager1(); UnloadApplication(GURL(kTestServiceURL));
std::set<TransportNodeId> nodes; std::set<TransportNodeId> nodes;
nodes.insert(node1_id); nodes.insert(node_id);
WaitForDestruction(view_manager_2(), &nodes, NULL); WaitForDestruction(embedded, &nodes, NULL);
// tree() should still be valid, since it's owned by neither connection. EXPECT_EQ(NULL, embedded->tree());
EXPECT_TRUE(view_manager_2()->tree()->children().empty()); // node was owned by the window manager, so it should be gone.
// node1 was owned by the first connection, so it should be gone. EXPECT_EQ(NULL, embedded->GetNodeById(node_id));
EXPECT_EQ(NULL, view_manager_2()->GetNodeById(node1_id)); // view_in_embedded was owned by the embedded app, so it should still exist,
// view1_2 was owned by the second connection, so it should still exist, but // but disconnected from the node tree.
// disconnected from the node tree. EXPECT_EQ(view_in_embedded, embedded->GetViewById(view_id));
View* another_view1_2 = view_manager_2()->GetViewById(view1_2_id); EXPECT_EQ(NULL, view_in_embedded->node());
EXPECT_EQ(view1_2, another_view1_2);
EXPECT_EQ(NULL, view1_2->node());
} }
// This test verifies that it is not possible to set the active view to a view // This test verifies that it is not possible to set the active view to a view
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment