Index: mojo/shell/tests/loader_unittest.cc |
diff --git a/mojo/shell/tests/loader_unittest.cc b/mojo/shell/tests/loader_unittest.cc |
deleted file mode 100644 |
index b9c9f272c060cd6a6007e3abebff60a9a6f26f75..0000000000000000000000000000000000000000 |
--- a/mojo/shell/tests/loader_unittest.cc |
+++ /dev/null |
@@ -1,561 +0,0 @@ |
-// 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 <utility> |
- |
-#include "base/at_exit.h" |
-#include "base/bind.h" |
-#include "base/macros.h" |
-#include "base/memory/scoped_vector.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/run_loop.h" |
-#include "mojo/public/cpp/bindings/strong_binding.h" |
-#include "mojo/services/catalog/factory.h" |
-#include "mojo/services/catalog/store.h" |
-#include "mojo/shell/connect_util.h" |
-#include "mojo/shell/loader.h" |
-#include "mojo/shell/public/cpp/connector.h" |
-#include "mojo/shell/public/cpp/interface_factory.h" |
-#include "mojo/shell/public/cpp/shell_client.h" |
-#include "mojo/shell/public/cpp/shell_connection.h" |
-#include "mojo/shell/public/interfaces/interface_provider.mojom.h" |
-#include "mojo/shell/shell.h" |
-#include "mojo/shell/tests/test.mojom.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-namespace mojo { |
-namespace shell { |
-namespace test { |
- |
-const char kTestURLString[] = "test:testService"; |
-const char kTestAURLString[] = "test:TestA"; |
-const char kTestBURLString[] = "test:TestB"; |
- |
-struct TestContext { |
- TestContext() : num_impls(0), num_loader_deletes(0) {} |
- std::string last_test_string; |
- int num_impls; |
- int num_loader_deletes; |
-}; |
- |
-void QuitClosure(const Identity& expected, |
- bool* value, |
- const Identity& actual) { |
- if (expected == actual) { |
- *value = true; |
- base::MessageLoop::current()->QuitWhenIdle(); |
- } |
-} |
- |
-class TestServiceImpl : public TestService { |
- public: |
- TestServiceImpl(TestContext* context, InterfaceRequest<TestService> request) |
- : context_(context), binding_(this, std::move(request)) { |
- ++context_->num_impls; |
- } |
- |
- ~TestServiceImpl() override { |
- --context_->num_impls; |
- if (!base::MessageLoop::current()->is_running()) |
- return; |
- base::MessageLoop::current()->QuitWhenIdle(); |
- } |
- |
- // TestService implementation: |
- void Test(const String& test_string, |
- const Callback<void()>& callback) override { |
- context_->last_test_string = test_string; |
- callback.Run(); |
- } |
- |
- private: |
- TestContext* context_; |
- StrongBinding<TestService> binding_; |
-}; |
- |
-class TestClient { |
- public: |
- explicit TestClient(TestServicePtr service) |
- : service_(std::move(service)), quit_after_ack_(false) {} |
- |
- void AckTest() { |
- if (quit_after_ack_) |
- base::MessageLoop::current()->QuitWhenIdle(); |
- } |
- |
- void Test(const std::string& test_string) { |
- quit_after_ack_ = true; |
- service_->Test(test_string, |
- base::Bind(&TestClient::AckTest, base::Unretained(this))); |
- } |
- |
- private: |
- TestServicePtr service_; |
- bool quit_after_ack_; |
- DISALLOW_COPY_AND_ASSIGN(TestClient); |
-}; |
- |
-class TestLoader : public Loader, |
- public ShellClient, |
- public InterfaceFactory<TestService> { |
- public: |
- explicit TestLoader(TestContext* context) |
- : context_(context), num_loads_(0) {} |
- |
- ~TestLoader() override { |
- ++context_->num_loader_deletes; |
- shell_connection_.reset(); |
- } |
- |
- int num_loads() const { return num_loads_; } |
- const std::string& last_requestor_name() const { |
- return last_requestor_name_; |
- } |
- |
- private: |
- // Loader implementation. |
- void Load(const std::string& name, |
- mojom::ShellClientRequest request) override { |
- ++num_loads_; |
- shell_connection_.reset(new ShellConnection(this, std::move(request))); |
- } |
- |
- // mojo::ShellClient implementation. |
- bool AcceptConnection(Connection* connection) override { |
- connection->AddInterface<TestService>(this); |
- last_requestor_name_ = connection->GetRemoteIdentity().name(); |
- return true; |
- } |
- |
- // InterfaceFactory<TestService> implementation. |
- void Create(Connection* connection, |
- InterfaceRequest<TestService> request) override { |
- new TestServiceImpl(context_, std::move(request)); |
- } |
- |
- scoped_ptr<ShellConnection> shell_connection_; |
- TestContext* context_; |
- int num_loads_; |
- std::string last_requestor_name_; |
- |
- DISALLOW_COPY_AND_ASSIGN(TestLoader); |
-}; |
- |
-class ClosingLoader : public Loader { |
- private: |
- // Loader implementation. |
- void Load(const std::string& name, |
- mojom::ShellClientRequest request) override { |
- } |
-}; |
- |
-class TesterContext { |
- public: |
- explicit TesterContext(base::MessageLoop* loop) |
- : num_b_calls_(0), |
- num_c_calls_(0), |
- num_a_deletes_(0), |
- num_b_deletes_(0), |
- num_c_deletes_(0), |
- tester_called_quit_(false), |
- a_called_quit_(false), |
- loop_(loop) {} |
- |
- void IncrementNumBCalls() { |
- base::AutoLock lock(lock_); |
- num_b_calls_++; |
- } |
- |
- void IncrementNumCCalls() { |
- base::AutoLock lock(lock_); |
- num_c_calls_++; |
- } |
- |
- void IncrementNumADeletes() { |
- base::AutoLock lock(lock_); |
- num_a_deletes_++; |
- } |
- |
- void IncrementNumBDeletes() { |
- base::AutoLock lock(lock_); |
- num_b_deletes_++; |
- } |
- |
- void IncrementNumCDeletes() { |
- base::AutoLock lock(lock_); |
- num_c_deletes_++; |
- } |
- |
- void set_tester_called_quit() { |
- base::AutoLock lock(lock_); |
- tester_called_quit_ = true; |
- } |
- |
- void set_a_called_quit() { |
- base::AutoLock lock(lock_); |
- a_called_quit_ = true; |
- } |
- |
- int num_b_calls() { |
- base::AutoLock lock(lock_); |
- return num_b_calls_; |
- } |
- int num_c_calls() { |
- base::AutoLock lock(lock_); |
- return num_c_calls_; |
- } |
- int num_a_deletes() { |
- base::AutoLock lock(lock_); |
- return num_a_deletes_; |
- } |
- int num_b_deletes() { |
- base::AutoLock lock(lock_); |
- return num_b_deletes_; |
- } |
- int num_c_deletes() { |
- base::AutoLock lock(lock_); |
- return num_c_deletes_; |
- } |
- bool tester_called_quit() { |
- base::AutoLock lock(lock_); |
- return tester_called_quit_; |
- } |
- bool a_called_quit() { |
- base::AutoLock lock(lock_); |
- return a_called_quit_; |
- } |
- |
- void QuitSoon() { |
- loop_->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); |
- } |
- |
- private: |
- // lock_ protects all members except for loop_ which must be unchanged for the |
- // lifetime of this class. |
- base::Lock lock_; |
- int num_b_calls_; |
- int num_c_calls_; |
- int num_a_deletes_; |
- int num_b_deletes_; |
- int num_c_deletes_; |
- bool tester_called_quit_; |
- bool a_called_quit_; |
- |
- base::MessageLoop* loop_; |
-}; |
- |
-// Used to test that the requestor name will be correctly passed. |
-class TestAImpl : public TestA { |
- public: |
- TestAImpl(Connector* connector, |
- TesterContext* test_context, |
- InterfaceRequest<TestA> request, |
- InterfaceFactory<TestC>* factory) |
- : test_context_(test_context), binding_(this, std::move(request)) { |
- connection_ = connector->Connect(kTestBURLString); |
- connection_->AddInterface<TestC>(factory); |
- connection_->GetInterface(&b_); |
- } |
- |
- ~TestAImpl() override { |
- test_context_->IncrementNumADeletes(); |
- if (base::MessageLoop::current()->is_running()) |
- Quit(); |
- } |
- |
- private: |
- void CallB() override { |
- b_->B(base::Bind(&TestAImpl::Quit, base::Unretained(this))); |
- } |
- |
- void CallCFromB() override { |
- b_->CallC(base::Bind(&TestAImpl::Quit, base::Unretained(this))); |
- } |
- |
- void Quit() { |
- base::MessageLoop::current()->QuitWhenIdle(); |
- test_context_->set_a_called_quit(); |
- test_context_->QuitSoon(); |
- } |
- |
- scoped_ptr<Connection> connection_; |
- TesterContext* test_context_; |
- TestBPtr b_; |
- StrongBinding<TestA> binding_; |
-}; |
- |
-class TestBImpl : public TestB { |
- public: |
- TestBImpl(Connection* connection, |
- TesterContext* test_context, |
- InterfaceRequest<TestB> request) |
- : test_context_(test_context), binding_(this, std::move(request)) { |
- connection->GetInterface(&c_); |
- } |
- |
- ~TestBImpl() override { |
- test_context_->IncrementNumBDeletes(); |
- if (base::MessageLoop::current()->is_running()) |
- base::MessageLoop::current()->QuitWhenIdle(); |
- test_context_->QuitSoon(); |
- } |
- |
- private: |
- void B(const Callback<void()>& callback) override { |
- test_context_->IncrementNumBCalls(); |
- callback.Run(); |
- } |
- |
- void CallC(const Callback<void()>& callback) override { |
- test_context_->IncrementNumBCalls(); |
- c_->C(callback); |
- } |
- |
- TesterContext* test_context_; |
- TestCPtr c_; |
- StrongBinding<TestB> binding_; |
-}; |
- |
-class TestCImpl : public TestC { |
- public: |
- TestCImpl(Connection* connection, |
- TesterContext* test_context, |
- InterfaceRequest<TestC> request) |
- : test_context_(test_context), binding_(this, std::move(request)) {} |
- |
- ~TestCImpl() override { test_context_->IncrementNumCDeletes(); } |
- |
- private: |
- void C(const Callback<void()>& callback) override { |
- test_context_->IncrementNumCCalls(); |
- callback.Run(); |
- } |
- |
- TesterContext* test_context_; |
- StrongBinding<TestC> binding_; |
-}; |
- |
-class Tester : public ShellClient, |
- public Loader, |
- public InterfaceFactory<TestA>, |
- public InterfaceFactory<TestB>, |
- public InterfaceFactory<TestC> { |
- public: |
- Tester(TesterContext* context, const std::string& requestor_name) |
- : context_(context), requestor_name_(requestor_name) {} |
- ~Tester() override {} |
- |
- private: |
- void Load(const std::string& name, |
- InterfaceRequest<mojom::ShellClient> request) override { |
- app_.reset(new ShellConnection(this, std::move(request))); |
- } |
- |
- bool AcceptConnection(Connection* connection) override { |
- if (!requestor_name_.empty() && |
- requestor_name_ != connection->GetRemoteIdentity().name()) { |
- context_->set_tester_called_quit(); |
- context_->QuitSoon(); |
- base::MessageLoop::current()->QuitWhenIdle(); |
- return false; |
- } |
- // If we're coming from A, then add B, otherwise A. |
- if (connection->GetRemoteIdentity().name() == kTestAURLString) |
- connection->AddInterface<TestB>(this); |
- else |
- connection->AddInterface<TestA>(this); |
- return true; |
- } |
- |
- void Create(Connection* connection, |
- InterfaceRequest<TestA> request) override { |
- a_bindings_.push_back( |
- new TestAImpl(app_->connector(), context_, std::move(request), this)); |
- } |
- |
- void Create(Connection* connection, |
- InterfaceRequest<TestB> request) override { |
- new TestBImpl(connection, context_, std::move(request)); |
- } |
- |
- void Create(Connection* connection, |
- InterfaceRequest<TestC> request) override { |
- new TestCImpl(connection, context_, std::move(request)); |
- } |
- |
- TesterContext* context_; |
- scoped_ptr<ShellConnection> app_; |
- std::string requestor_name_; |
- ScopedVector<TestAImpl> a_bindings_; |
-}; |
- |
-void OnConnect(base::RunLoop* loop, mojom::ConnectResult result, |
- const String& user_id, uint32_t instance_id) { |
- loop->Quit(); |
-} |
- |
-class LoaderTest : public testing::Test { |
- public: |
- LoaderTest() : tester_context_(&loop_) {} |
- ~LoaderTest() override {} |
- |
- void SetUp() override { |
- blocking_pool_ = new base::SequencedWorkerPool(3, "blocking_pool"); |
- catalog_.reset( |
- new catalog::Factory(blocking_pool_.get(), nullptr, nullptr)); |
- shell_.reset(new Shell(nullptr, catalog_->TakeShellClient())); |
- test_loader_ = new TestLoader(&context_); |
- shell_->set_default_loader(scoped_ptr<Loader>(test_loader_)); |
- |
- TestServicePtr service_proxy; |
- ConnectToInterface(kTestURLString, &service_proxy); |
- test_client_.reset(new TestClient(std::move(service_proxy))); |
- } |
- |
- void TearDown() override { |
- test_client_.reset(); |
- shell_.reset(); |
- blocking_pool_->Shutdown(); |
- } |
- |
- void AddLoaderForName(const std::string& name, |
- const std::string& requestor_name) { |
- shell_->SetLoaderForName( |
- make_scoped_ptr(new Tester(&tester_context_, requestor_name)), name); |
- } |
- |
- bool HasRunningInstanceForName(const std::string& name) { |
- Shell::TestAPI test_api(shell_.get()); |
- return test_api.HasRunningInstanceForName(name); |
- } |
- |
- protected: |
- template <typename Interface> |
- void ConnectToInterface(const std::string& name, |
- InterfacePtr<Interface>* ptr) { |
- base::RunLoop loop; |
- mojom::InterfaceProviderPtr remote_interfaces; |
- scoped_ptr<ConnectParams> params(new ConnectParams); |
- params->set_source(CreateShellIdentity()); |
- params->set_target(Identity(name, mojom::kRootUserID)); |
- params->set_remote_interfaces(GetProxy(&remote_interfaces)); |
- params->set_connect_callback( |
- base::Bind(&OnConnect, base::Unretained(&loop))); |
- shell_->Connect(std::move(params)); |
- loop.Run(); |
- |
- mojo::GetInterface(remote_interfaces.get(), ptr); |
- } |
- |
- base::ShadowingAtExitManager at_exit_; |
- TestLoader* test_loader_; |
- TesterContext tester_context_; |
- TestContext context_; |
- base::MessageLoop loop_; |
- scoped_ptr<TestClient> test_client_; |
- scoped_ptr<catalog::Factory> catalog_; |
- scoped_refptr<base::SequencedWorkerPool> blocking_pool_; |
- scoped_ptr<Shell> shell_; |
- DISALLOW_COPY_AND_ASSIGN(LoaderTest); |
-}; |
- |
-TEST_F(LoaderTest, Basic) { |
- test_client_->Test("test"); |
- loop_.Run(); |
- EXPECT_EQ(std::string("test"), context_.last_test_string); |
-} |
- |
-TEST_F(LoaderTest, ClientError) { |
- test_client_->Test("test"); |
- EXPECT_TRUE(HasRunningInstanceForName(kTestURLString)); |
- loop_.Run(); |
- EXPECT_EQ(1, context_.num_impls); |
- test_client_.reset(); |
- loop_.Run(); |
- EXPECT_EQ(0, context_.num_impls); |
- EXPECT_TRUE(HasRunningInstanceForName(kTestURLString)); |
-} |
- |
-TEST_F(LoaderTest, Deletes) { |
- { |
- catalog::Factory catalog(blocking_pool_.get(), nullptr, nullptr); |
- Shell shell(nullptr, catalog.TakeShellClient()); |
- TestLoader* default_loader = new TestLoader(&context_); |
- TestLoader* name_loader1 = new TestLoader(&context_); |
- TestLoader* name_loader2 = new TestLoader(&context_); |
- shell.set_default_loader(scoped_ptr<Loader>(default_loader)); |
- shell.SetLoaderForName(scoped_ptr<Loader>(name_loader1), "test:test1"); |
- shell.SetLoaderForName(scoped_ptr<Loader>(name_loader2), "test:test1"); |
- } |
- EXPECT_EQ(3, context_.num_loader_deletes); |
-} |
- |
-// Test for SetLoaderForName() & set_default_loader(). |
-TEST_F(LoaderTest, SetLoaders) { |
- TestLoader* default_loader = new TestLoader(&context_); |
- TestLoader* name_loader = new TestLoader(&context_); |
- shell_->set_default_loader(scoped_ptr<Loader>(default_loader)); |
- shell_->SetLoaderForName(scoped_ptr<Loader>(name_loader), "test:test1"); |
- |
- // test::test1 should go to name_loader. |
- TestServicePtr test_service; |
- ConnectToInterface("test:test1", &test_service); |
- EXPECT_EQ(1, name_loader->num_loads()); |
- EXPECT_EQ(0, default_loader->num_loads()); |
- |
- // http::test1 should go to default loader. |
- ConnectToInterface("http:test1", &test_service); |
- EXPECT_EQ(1, name_loader->num_loads()); |
- EXPECT_EQ(1, default_loader->num_loads()); |
-} |
- |
-TEST_F(LoaderTest, NoServiceNoLoad) { |
- AddLoaderForName(kTestAURLString, std::string()); |
- |
- // There is no TestC service implementation registered with the Shell, so this |
- // cannot succeed (but also shouldn't crash). |
- TestCPtr c; |
- ConnectToInterface(kTestAURLString, &c); |
- c.set_connection_error_handler( |
- []() { base::MessageLoop::current()->QuitWhenIdle(); }); |
- |
- loop_.Run(); |
- EXPECT_TRUE(c.encountered_error()); |
-} |
- |
-TEST_F(LoaderTest, TestEndApplicationClosure) { |
- ClosingLoader* loader = new ClosingLoader(); |
- shell_->SetLoaderForName(scoped_ptr<Loader>(loader), "test:test"); |
- |
- bool called = false; |
- scoped_ptr<ConnectParams> params(new ConnectParams); |
- params->set_source(CreateShellIdentity()); |
- params->set_target(Identity("test:test", mojom::kRootUserID)); |
- shell_->SetInstanceQuitCallback( |
- base::Bind(&QuitClosure, params->target(), &called)); |
- shell_->Connect(std::move(params)); |
- loop_.Run(); |
- EXPECT_TRUE(called); |
-} |
- |
-TEST_F(LoaderTest, SameIdentityShouldNotCauseDuplicateLoad) { |
- // 1 because LoaderTest connects once at startup. |
- EXPECT_EQ(1, test_loader_->num_loads()); |
- |
- TestServicePtr test_service; |
- ConnectToInterface("test:foo", &test_service); |
- EXPECT_EQ(2, test_loader_->num_loads()); |
- |
- // Exactly the same name as above. |
- ConnectToInterface("test:foo", &test_service); |
- EXPECT_EQ(2, test_loader_->num_loads()); |
- |
- // A different identity because the domain is different. |
- ConnectToInterface("test:bar", &test_service); |
- EXPECT_EQ(3, test_loader_->num_loads()); |
-} |
- |
-} // namespace test |
-} // namespace shell |
-} // namespace mojo |