Commit 1124dea0 authored by sky@chromium.org's avatar sky@chromium.org

Changes view manager test to connect via shell

Previously code was linking with ViewManager, now I'm connecting
through the shell. As part of this I'm adding a general class that
should make it easy to connect to any server through the shell.

For the time being I'm making the shell explicitly link with the
viewmanager. Eventually that'll have to change.

BUG=365012
TEST=covered by tests
R=davemoore@chromium.org

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@266937 0039d316-1c4b-4281-b951-d872f2087c98
parent 6ba332af
...@@ -438,6 +438,7 @@ ...@@ -438,6 +438,7 @@
'dependencies': [ 'dependencies': [
'../base/base.gyp:base', '../base/base.gyp:base',
'../base/base.gyp:base_static', '../base/base.gyp:base_static',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../net/net.gyp:net', '../net/net.gyp:net',
'../url/url.gyp:url_lib', '../url/url.gyp:url_lib',
'mojo_external_service_bindings', 'mojo_external_service_bindings',
...@@ -501,6 +502,30 @@ ...@@ -501,6 +502,30 @@
'../dbus/dbus.gyp:dbus', '../dbus/dbus.gyp:dbus',
], ],
}], }],
['use_aura==1', {
'dependencies': [
# These are only necessary as long as we hard code use of ViewManager.
'../skia/skia.gyp:skia',
'mojo_shell_client',
'mojo_view_manager',
],
}],
],
},
{
'target_name': 'mojo_shell_test_support',
'type': 'static_library',
'dependencies': [
'../base/base.gyp:base',
'../base/base.gyp:base_static',
'../url/url.gyp:url_lib',
'mojo_service_manager',
'mojo_shell_lib',
'mojo_system_impl',
],
'sources': [
'shell/shell_test_helper.cc',
'shell/shell_test_helper.h',
], ],
}, },
{ {
......
...@@ -216,14 +216,14 @@ ...@@ -216,14 +216,14 @@
'type': 'executable', 'type': 'executable',
'dependencies': [ 'dependencies': [
'../base/base.gyp:base', '../base/base.gyp:base',
'../base/base.gyp:run_all_unittests',
'../skia/skia.gyp:skia', '../skia/skia.gyp:skia',
'../testing/gtest.gyp:gtest', '../testing/gtest.gyp:gtest',
'../ui/aura/aura.gyp:aura', '../ui/aura/aura.gyp:aura',
'mojo_environment_chromium', 'mojo_environment_chromium',
'mojo_run_all_unittests',
'mojo_shell_client', 'mojo_shell_client',
'mojo_shell_test_support',
'mojo_system_impl', 'mojo_system_impl',
'mojo_view_manager',
'mojo_view_manager_bindings', 'mojo_view_manager_bindings',
], ],
'sources': [ 'sources': [
......
...@@ -58,14 +58,59 @@ class ServiceManager::ServiceFactory : public Shell, public ErrorHandler { ...@@ -58,14 +58,59 @@ class ServiceManager::ServiceFactory : public Shell, public ErrorHandler {
ServiceManager* const manager_; ServiceManager* const manager_;
const GURL url_; const GURL url_;
RemotePtr<ShellClient> shell_client_; RemotePtr<ShellClient> shell_client_;
DISALLOW_COPY_AND_ASSIGN(ServiceFactory); DISALLOW_COPY_AND_ASSIGN(ServiceFactory);
}; };
class ServiceManager::TestAPI::TestShellConnection
: public Shell,
public ErrorHandler {
public:
explicit TestShellConnection(ServiceManager* manager) : manager_(manager) {
InterfacePipe<Shell> pipe;
shell_client_.reset(pipe.handle_to_peer.Pass(), this, this);
shell_handle_ = pipe.handle_to_self.Pass();
}
virtual ~TestShellConnection() {}
ScopedShellHandle GetShellHandle() {
return shell_handle_.Pass();
}
// Shell:
virtual void Connect(const String& url,
ScopedMessagePipeHandle client_pipe) OVERRIDE {
manager_->Connect(GURL(url.To<std::string>()), client_pipe.Pass());
}
virtual void OnError() OVERRIDE {
}
private:
ServiceManager* manager_;
RemotePtr<ShellClient> shell_client_;
ScopedShellHandle shell_handle_;
DISALLOW_COPY_AND_ASSIGN(TestShellConnection);
};
// static // static
ServiceManager::TestAPI::TestAPI(ServiceManager* manager) : manager_(manager) {
}
ServiceManager::TestAPI::~TestAPI() {
}
bool ServiceManager::TestAPI::HasCreatedInstance() { bool ServiceManager::TestAPI::HasCreatedInstance() {
return has_created_instance; return has_created_instance;
} }
ScopedShellHandle ServiceManager::TestAPI::GetShellHandle() {
if (!shell_connection_.get())
shell_connection_.reset(new TestShellConnection(manager_));
return shell_connection_->GetShellHandle().Pass();
}
bool ServiceManager::TestAPI::HasFactoryForURL(const GURL& url) const { bool ServiceManager::TestAPI::HasFactoryForURL(const GURL& url) const {
return manager_->url_to_service_factory_.find(url) != return manager_->url_to_service_factory_.find(url) !=
manager_->url_to_service_factory_.end(); manager_->url_to_service_factory_.end();
......
...@@ -16,27 +16,32 @@ ...@@ -16,27 +16,32 @@
#include "mojo/service_manager/service_manager_export.h" #include "mojo/service_manager/service_manager_export.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace content {
class MojoTest;
}
namespace mojo { namespace mojo {
class MOJO_SERVICE_MANAGER_EXPORT ServiceManager { class MOJO_SERVICE_MANAGER_EXPORT ServiceManager {
public: public:
// API for testing. // API for testing.
class MOJO_SERVICE_MANAGER_EXPORT TestAPI { class MOJO_SERVICE_MANAGER_EXPORT TestAPI {
private: public:
friend class ServiceManagerTest; explicit TestAPI(ServiceManager* manager);
friend class content::MojoTest; ~TestAPI();
// Returns a handle to the shell.
ScopedShellHandle GetShellHandle();
explicit TestAPI(ServiceManager* manager) : manager_(manager) {}
// Returns true if the shared instance has been created. // Returns true if the shared instance has been created.
static bool HasCreatedInstance(); static bool HasCreatedInstance();
// Returns true if there is a ServiceFactory for this URL. // Returns true if there is a ServiceFactory for this URL.
bool HasFactoryForURL(const GURL& url) const; bool HasFactoryForURL(const GURL& url) const;
private:
class TestShellConnection;
ServiceManager* manager_; ServiceManager* manager_;
scoped_ptr<TestShellConnection> shell_connection_;
DISALLOW_COPY_AND_ASSIGN(TestAPI);
}; };
// Interface class for debugging only. // Interface class for debugging only.
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "mojo/services/view_manager/view_manager_connection.h"
#include <string> #include <string>
#include <vector> #include <vector>
...@@ -14,7 +12,8 @@ ...@@ -14,7 +12,8 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "mojo/public/cpp/bindings/allocation_scope.h" #include "mojo/public/cpp/bindings/allocation_scope.h"
#include "mojo/public/cpp/environment/environment.h" #include "mojo/public/cpp/environment/environment.h"
#include "mojo/services/view_manager/root_node_manager.h" #include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h"
#include "mojo/shell/shell_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace mojo { namespace mojo {
...@@ -25,6 +24,17 @@ namespace { ...@@ -25,6 +24,17 @@ namespace {
base::RunLoop* current_run_loop = NULL; base::RunLoop* current_run_loop = NULL;
// TODO(sky): remove and include a common header.
typedef uint32_t ChangeId;
uint16_t FirstIdFromTransportId(uint32_t id) {
return static_cast<uint16_t>((id >> 16) & 0xFFFF);
}
uint16_t SecondIdFromTransportId(uint32_t id) {
return static_cast<uint16_t>(id & 0xFFFF);
}
// Sets |current_run_loop| and runs it. It is expected that someone else quits // Sets |current_run_loop| and runs it. It is expected that someone else quits
// the loop. // the loop.
void DoRunLoop() { void DoRunLoop() {
...@@ -50,12 +60,12 @@ void BooleanCallback(bool* result_cache, bool result) { ...@@ -50,12 +60,12 @@ void BooleanCallback(bool* result_cache, bool result) {
// Creates an id used for transport from the specified parameters. // Creates an id used for transport from the specified parameters.
uint32_t CreateNodeId(uint16_t connection_id, uint16_t node_id) { uint32_t CreateNodeId(uint16_t connection_id, uint16_t node_id) {
return NodeIdToTransportId(NodeId(connection_id, node_id)); return (connection_id << 16) | node_id;
} }
// Creates an id used for transport from the specified parameters. // Creates an id used for transport from the specified parameters.
uint32_t CreateViewId(uint16_t connection_id, uint16_t view_id) { uint32_t CreateViewId(uint16_t connection_id, uint16_t view_id) {
return ViewIdToTransportId(ViewId(connection_id, view_id)); return (connection_id << 16) | view_id;
} }
// Creates a node with the specified id. Returns true on success. Blocks until // Creates a node with the specified id. Returns true on success. Blocks until
...@@ -133,8 +143,6 @@ class ViewManagerClientImpl : public ViewManagerClient { ...@@ -133,8 +143,6 @@ class ViewManagerClientImpl : public ViewManagerClient {
public: public:
ViewManagerClientImpl() : id_(0), quit_count_(0) {} ViewManagerClientImpl() : id_(0), quit_count_(0) {}
void set_quit_count(int count) { quit_count_ = count; }
uint16_t id() const { return id_; } uint16_t id() const { return id_; }
Changes GetAndClearChanges() { Changes GetAndClearChanges() {
...@@ -143,10 +151,23 @@ class ViewManagerClientImpl : public ViewManagerClient { ...@@ -143,10 +151,23 @@ class ViewManagerClientImpl : public ViewManagerClient {
return changes; return changes;
} }
void WaitForId() {
if (id_ == 0)
DoRunLoop();
}
void DoRunLoopUntilChangesCount(size_t count) {
if (changes_.size() >= count)
return;
quit_count_ = count - changes_.size();
DoRunLoop();
}
private: private:
// ViewManagerClient overrides: // ViewManagerClient overrides:
virtual void OnConnectionEstablished(uint16_t connection_id) OVERRIDE { virtual void OnConnectionEstablished(uint16_t connection_id) OVERRIDE {
id_ = connection_id; id_ = connection_id;
if (current_run_loop)
current_run_loop->Quit(); current_run_loop->Quit();
} }
virtual void OnNodeHierarchyChanged(uint32_t node, virtual void OnNodeHierarchyChanged(uint32_t node,
...@@ -182,7 +203,7 @@ class ViewManagerClientImpl : public ViewManagerClient { ...@@ -182,7 +203,7 @@ class ViewManagerClientImpl : public ViewManagerClient {
uint16_t id_; uint16_t id_;
// Used to determine when/if to quit the run loop. // Used to determine when/if to quit the run loop.
int quit_count_; size_t quit_count_;
Changes changes_; Changes changes_;
...@@ -191,47 +212,45 @@ class ViewManagerClientImpl : public ViewManagerClient { ...@@ -191,47 +212,45 @@ class ViewManagerClientImpl : public ViewManagerClient {
class ViewManagerConnectionTest : public testing::Test { class ViewManagerConnectionTest : public testing::Test {
public: public:
ViewManagerConnectionTest() : service_factory_(&root_node_manager_) {} ViewManagerConnectionTest() {}
virtual void SetUp() OVERRIDE { virtual void SetUp() OVERRIDE {
InterfacePipe<ViewManagerClient, ViewManager> pipe; AllocationScope allocation_scope;
view_manager_.reset(pipe.handle_to_peer.Pass(), &client_);
connection_.Initialize( test_helper_.Init();
&service_factory_,
ScopedMessagePipeHandle::From(pipe.handle_to_self.Pass())); InterfacePipe<ViewManager, AnyInterface> pipe;
// Wait for the id. test_helper_.shell()->Connect("mojo:mojo_view_manager",
DoRunLoop(); pipe.handle_to_peer.Pass());
view_manager_.reset(pipe.handle_to_self.Pass(), &client_);
client_.WaitForId();
} }
protected: protected:
// Creates a second connection to the viewmanager. // Creates a second connection to the viewmanager.
void EstablishSecondConnection() { void EstablishSecondConnection() {
connection2_.reset(new ViewManagerConnection); AllocationScope allocation_scope;
InterfacePipe<ViewManagerClient, ViewManager> pipe; InterfacePipe<ViewManager, AnyInterface> pipe;
view_manager2_.reset(pipe.handle_to_peer.Pass(), &client2_); test_helper_.shell()->Connect("mojo:mojo_view_manager",
connection2_->Initialize( pipe.handle_to_peer.Pass());
&service_factory_, view_manager2_.reset(pipe.handle_to_self.Pass(), &client2_);
ScopedMessagePipeHandle::From(pipe.handle_to_self.Pass()));
// Wait for the id. client2_.WaitForId();
DoRunLoop();
} }
void DestroySecondConnection() { void DestroySecondConnection() {
connection2_.reset();
view_manager2_.reset(); view_manager2_.reset();
} }
Environment env_;
base::MessageLoop loop_; base::MessageLoop loop_;
RootNodeManager root_node_manager_; shell::ShellTestHelper test_helper_;
ServiceConnector<ViewManagerConnection, RootNodeManager> service_factory_;
ViewManagerConnection connection_;
ViewManagerClientImpl client_; ViewManagerClientImpl client_;
RemotePtr<ViewManager> view_manager_; RemotePtr<ViewManager> view_manager_;
ViewManagerClientImpl client2_; ViewManagerClientImpl client2_;
RemotePtr<ViewManager> view_manager2_; RemotePtr<ViewManager> view_manager2_;
scoped_ptr<ViewManagerConnection> connection2_;
DISALLOW_COPY_AND_ASSIGN(ViewManagerConnectionTest); DISALLOW_COPY_AND_ASSIGN(ViewManagerConnectionTest);
}; };
...@@ -317,12 +336,8 @@ TEST_F(ViewManagerConnectionTest, AddRemoveNotifyMultipleConnections) { ...@@ -317,12 +336,8 @@ TEST_F(ViewManagerConnectionTest, AddRemoveNotifyMultipleConnections) {
// Second client should also have received the change. // Second client should also have received the change.
{ {
client2_.DoRunLoopUntilChangesCount(1);
Changes changes(client2_.GetAndClearChanges()); Changes changes(client2_.GetAndClearChanges());
if (changes.empty()) {
client2_.set_quit_count(1);
DoRunLoop();
changes = client2_.GetAndClearChanges();
}
ASSERT_EQ(1u, changes.size()); ASSERT_EQ(1u, changes.size());
EXPECT_EQ("change_id=0 node=1,2 new_parent=1,1 old_parent=null", EXPECT_EQ("change_id=0 node=1,2 new_parent=1,1 old_parent=null",
changes[0]); changes[0]);
...@@ -500,10 +515,12 @@ TEST_F(ViewManagerConnectionTest, SetViewFromSecondConnection) { ...@@ -500,10 +515,12 @@ TEST_F(ViewManagerConnectionTest, SetViewFromSecondConnection) {
CreateNodeId(client_.id(), 1), CreateNodeId(client_.id(), 1),
CreateViewId(client2_.id(), 51), CreateViewId(client2_.id(), 51),
22)); 22));
client_.DoRunLoopUntilChangesCount(1);
Changes changes(client_.GetAndClearChanges()); Changes changes(client_.GetAndClearChanges());
ASSERT_EQ(1u, changes.size()); ASSERT_EQ(1u, changes.size());
EXPECT_EQ("change_id=0 node=1,1 new_view=2,51 old_view=null", changes[0]); EXPECT_EQ("change_id=0 node=1,1 new_view=2,51 old_view=null", changes[0]);
client2_.DoRunLoopUntilChangesCount(1);
changes = client2_.GetAndClearChanges(); changes = client2_.GetAndClearChanges();
ASSERT_EQ(1u, changes.size()); ASSERT_EQ(1u, changes.size());
EXPECT_EQ("change_id=22 node=1,1 new_view=2,51 old_view=null", changes[0]); EXPECT_EQ("change_id=22 node=1,1 new_view=2,51 old_view=null", changes[0]);
...@@ -512,8 +529,7 @@ TEST_F(ViewManagerConnectionTest, SetViewFromSecondConnection) { ...@@ -512,8 +529,7 @@ TEST_F(ViewManagerConnectionTest, SetViewFromSecondConnection) {
// Shutdown the second connection and verify view is removed. // Shutdown the second connection and verify view is removed.
{ {
DestroySecondConnection(); DestroySecondConnection();
client_.set_quit_count(1); client_.DoRunLoopUntilChangesCount(1);
DoRunLoop();
Changes changes(client_.GetAndClearChanges()); Changes changes(client_.GetAndClearChanges());
ASSERT_EQ(1u, changes.size()); ASSERT_EQ(1u, changes.size());
......
...@@ -4,10 +4,13 @@ ...@@ -4,10 +4,13 @@
#include "mojo/shell/context.h" #include "mojo/shell/context.h"
#include "base/command_line.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/memory/scoped_vector.h"
#include "mojo/embedder/embedder.h" #include "mojo/embedder/embedder.h"
#include "mojo/gles2/gles2_support_impl.h" #include "mojo/gles2/gles2_support_impl.h"
#include "mojo/public/cpp/shell/application.h"
#include "mojo/service_manager/service_loader.h" #include "mojo/service_manager/service_loader.h"
#include "mojo/service_manager/service_manager.h" #include "mojo/service_manager/service_manager.h"
#include "mojo/services/native_viewport/native_viewport_service.h" #include "mojo/services/native_viewport/native_viewport_service.h"
...@@ -22,8 +25,62 @@ ...@@ -22,8 +25,62 @@
#include "mojo/shell/dbus_service_loader_linux.h" #include "mojo/shell/dbus_service_loader_linux.h"
#endif // defined(OS_LINUX) #endif // defined(OS_LINUX)
#if defined(USE_AURA)
#include "mojo/services/view_manager/root_node_manager.h"
#include "mojo/services/view_manager/view_manager_connection.h"
#endif
namespace mojo { namespace mojo {
namespace shell { namespace shell {
namespace {
// Used to ensure we only init once.
class Setup {
public:
Setup() {
embedder::Init();
gles2::GLES2SupportImpl::Init();
}
~Setup() {
}
private:
DISALLOW_COPY_AND_ASSIGN(Setup);
};
static base::LazyInstance<Setup> setup = LAZY_INSTANCE_INITIALIZER;
#if defined(USE_AURA)
class ViewManagerLoader : public ServiceLoader {
public:
ViewManagerLoader() {}
virtual ~ViewManagerLoader() {}
private:
virtual void LoadService(ServiceManager* manager,
const GURL& url,
ScopedShellHandle shell_handle) OVERRIDE {
scoped_ptr<Application> app(new Application(shell_handle.Pass()));
app->AddServiceConnector(
new ServiceConnector<services::view_manager::ViewManagerConnection,
services::view_manager::RootNodeManager>(
&root_node_manager_));
apps_.push_back(app.release());
}
virtual void OnServiceError(ServiceManager* manager,
const GURL& url) OVERRIDE {
}
services::view_manager::RootNodeManager root_node_manager_;
ScopedVector<Application> apps_;
DISALLOW_COPY_AND_ASSIGN(ViewManagerLoader);
};
#endif
} // namespace
class Context::NativeViewportServiceLoader : public ServiceLoader { class Context::NativeViewportServiceLoader : public ServiceLoader {
public: public:
...@@ -54,9 +111,7 @@ Context::Context() ...@@ -54,9 +111,7 @@ Context::Context()
task_runners_.cache_runner(), task_runners_.cache_runner(),
scoped_ptr<net::NetworkDelegate>(new NetworkDelegate()), scoped_ptr<net::NetworkDelegate>(new NetworkDelegate()),
storage_.profile_path()) { storage_.profile_path()) {
embedder::Init(); setup.Get();
gles2::GLES2SupportImpl::Init();
CommandLine* cmdline = CommandLine::ForCurrentProcess(); CommandLine* cmdline = CommandLine::ForCurrentProcess();
scoped_ptr<DynamicServiceRunnerFactory> runner_factory; scoped_ptr<DynamicServiceRunnerFactory> runner_factory;
if (cmdline->HasSwitch(switches::kEnableMultiprocess)) if (cmdline->HasSwitch(switches::kEnableMultiprocess))
...@@ -70,6 +125,12 @@ Context::Context() ...@@ -70,6 +125,12 @@ Context::Context()
service_manager_.SetLoaderForURL( service_manager_.SetLoaderForURL(
scoped_ptr<ServiceLoader>(new NativeViewportServiceLoader(this)), scoped_ptr<ServiceLoader>(new NativeViewportServiceLoader(this)),
GURL("mojo:mojo_native_viewport_service")); GURL("mojo:mojo_native_viewport_service"));
#if defined(USE_AURA)
// TODO(sky): need a better way to find this. It shouldn't be linked in.
service_manager_.SetLoaderForURL(
scoped_ptr<ServiceLoader>(new ViewManagerLoader()),
GURL("mojo:mojo_view_manager"));
#endif
#if defined(OS_LINUX) #if defined(OS_LINUX)
service_manager_.SetLoaderForScheme( service_manager_.SetLoaderForScheme(
......
...@@ -37,7 +37,6 @@ void Run(Context* context) { ...@@ -37,7 +37,6 @@ void Run(Context* context) {
ScopedMessagePipeHandle no_handle; ScopedMessagePipeHandle no_handle;
context->service_manager()->Connect(GURL(*it), no_handle.Pass()); context->service_manager()->Connect(GURL(*it), no_handle.Pass());
} }
// TODO(davemoore): Currently we leak |service_manager|.
} }
} // namespace shell } // namespace shell
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/shell/shell_test_helper.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "mojo/shell/context.h"
#include "mojo/shell/init.h"
namespace mojo {
namespace shell {
// State used on the background thread. Be careful, this is created on the main
// thread than passed to the shell thread. Destruction happens on the shell
// thread.
struct ShellTestHelper::State {
scoped_ptr<Context> context;
scoped_ptr<ServiceManager::TestAPI> test_api;
ScopedShellHandle shell_handle;
};
namespace {
void StartShellOnShellThread(ShellTestHelper::State* state) {
state->context.reset(new Context);
state->test_api.reset(
new ServiceManager::TestAPI(state->context->service_manager()));
state->shell_handle = state->test_api->GetShellHandle();
}
} // namespace
class ShellTestHelper::TestShellClient : public ShellClient {
public:
TestShellClient() {}
virtual ~TestShellClient() {}
// ShellClient:
virtual void AcceptConnection(
const mojo::String& url,
ScopedMessagePipeHandle client_handle) OVERRIDE {
}
private:
DISALLOW_COPY_AND_ASSIGN(TestShellClient);
};
ShellTestHelper::ShellTestHelper()
: shell_thread_("Test Shell Thread"),
state_(NULL) {
CommandLine::Init(0, NULL);
mojo::shell::InitializeLogging();
}
ShellTestHelper::~ShellTestHelper() {
if (state_) {
// |state_| contains data created on the background thread. Destroy it
// there so that there aren't any race conditions.
shell_thread_.message_loop()->DeleteSoon(FROM_HERE, state_);
state_ = NULL;
}
}
void ShellTestHelper::Init() {
DCHECK(!state_);
state_ = new State;
shell_thread_.Start();
shell_thread_.message_loop()->message_loop_proxy()->PostTaskAndReply(
FROM_HERE,
base::Bind(&StartShellOnShellThread, state_),
base::Bind(&ShellTestHelper::OnShellStarted, base::Unretained(this)));
run_loop_.reset(new base::RunLoop);
run_loop_->Run();
}
void ShellTestHelper::OnShellStarted() {
DCHECK(state_);
shell_client_.reset(new TestShellClient);
shell_.reset(state_->shell_handle.Pass(), shell_client_.get());
run_loop_->Quit();
}
} // namespace shell
} // namespace mojo
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_SHELL_SHELL_TEST_HELPER_
#define MOJO_SHELL_SHELL_TEST_HELPER_
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/threading/thread.h"
#include "mojo/public/cpp/bindings/remote_ptr.h"
#include "mojo/public/cpp/environment/environment.h"
#include "mojo/public/interfaces/shell/shell.mojom.h"
namespace base {
class MessageLoopProxy;
class RunLoop;
}
namespace mojo {
namespace shell {
// ShellTestHelper is useful for tests to establish a connection to the Shell.
// ShellTestHelper does this by spawning a thread and connecting. Invoke Init()
// to do this. Once done, shell() returns the handle to the Shell.
class ShellTestHelper {
public:
struct State;
ShellTestHelper();
~ShellTestHelper();
void Init();
// Returns a handle to the Shell. ShellTestHelper owns the shell.
Shell* shell() { return shell_.get(); }
private:
class TestShellClient;
// Invoked once connection has been established.
void OnShellStarted();
Environment environment_;
base::Thread shell_thread_;
// If non-null we're in Init() and waiting for connection.
scoped_ptr<base::RunLoop> run_loop_;
// See comment in declaration for details.
State* state_;
// Client interface for the shell.
scoped_ptr<TestShellClient> shell_client_;
RemotePtr<Shell> shell_;
DISALLOW_COPY_AND_ASSIGN(ShellTestHelper);
};
} // namespace shell
} // namespace mojo
#endif // MOJO_SHELL_SHELL_TEST_HELPER_
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