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

Unified Diff: mojo/shell/application_manager/application_manager_unittest.cc

Issue 1049993002: Get mojo_shell building inside chromium checkout. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix presubmit Created 5 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: mojo/shell/application_manager/application_manager_unittest.cc
diff --git a/mojo/shell/application_manager/application_manager_unittest.cc b/mojo/shell/application_manager/application_manager_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ed16d151352500e17a46f3d05af744a5fb1ee13f
--- /dev/null
+++ b/mojo/shell/application_manager/application_manager_unittest.cc
@@ -0,0 +1,829 @@
+// 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 "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 "mojo/public/cpp/application/application_connection.h"
+#include "mojo/public/cpp/application/application_delegate.h"
+#include "mojo/public/cpp/application/application_impl.h"
+#include "mojo/public/cpp/application/interface_factory.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/interfaces/application/service_provider.mojom.h"
+#include "mojo/shell/application_manager/application_loader.h"
+#include "mojo/shell/application_manager/application_manager.h"
+#include "mojo/shell/application_manager/test.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace shell {
+namespace {
+
+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(bool* value) {
+ *value = true;
+ base::MessageLoop::current()->QuitWhenIdle();
+}
+
+class QuitMessageLoopErrorHandler : public ErrorHandler {
+ public:
+ QuitMessageLoopErrorHandler() {}
+ ~QuitMessageLoopErrorHandler() override {}
+
+ // |ErrorHandler| implementation:
+ void OnConnectionError() override {
+ base::MessageLoop::current()->QuitWhenIdle();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuitMessageLoopErrorHandler);
+};
+
+class TestServiceImpl : public TestService {
+ public:
+ TestServiceImpl(TestContext* context, InterfaceRequest<TestService> request)
+ : context_(context), binding_(this, request.Pass()) {
+ ++context_->num_impls;
+ }
+
+ ~TestServiceImpl() override {
+ --context_->num_impls;
+ if (!base::MessageLoop::current()->is_running())
+ return;
+ base::MessageLoop::current()->Quit();
+ }
+
+ // 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_(service.Pass()), quit_after_ack_(false) {}
+
+ void AckTest() {
+ if (quit_after_ack_)
+ base::MessageLoop::current()->Quit();
+ }
+
+ 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 TestApplicationLoader : public ApplicationLoader,
+ public ApplicationDelegate,
+ public InterfaceFactory<TestService> {
+ public:
+ TestApplicationLoader() : context_(nullptr), num_loads_(0) {}
+
+ ~TestApplicationLoader() override {
+ if (context_)
+ ++context_->num_loader_deletes;
+ test_app_.reset();
+ }
+
+ void set_context(TestContext* context) { context_ = context; }
+ int num_loads() const { return num_loads_; }
+ const std::vector<std::string>& GetArgs() const { return test_app_->args(); }
+
+ private:
+ // ApplicationLoader implementation.
+ void Load(const GURL& url,
+ InterfaceRequest<Application> application_request) override {
+ ++num_loads_;
+ test_app_.reset(new ApplicationImpl(this, application_request.Pass()));
+ }
+
+ // ApplicationDelegate implementation.
+ bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
+ connection->AddService(this);
+ return true;
+ }
+
+ // InterfaceFactory implementation.
+ void Create(ApplicationConnection* connection,
+ InterfaceRequest<TestService> request) override {
+ new TestServiceImpl(context_, request.Pass());
+ }
+
+ scoped_ptr<ApplicationImpl> test_app_;
+ TestContext* context_;
+ int num_loads_;
+ DISALLOW_COPY_AND_ASSIGN(TestApplicationLoader);
+};
+
+class ClosingApplicationLoader : public ApplicationLoader {
+ private:
+ // ApplicationLoader implementation.
+ void Load(const GURL& url,
+ InterfaceRequest<Application> application_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 url will be correctly passed.
+class TestAImpl : public TestA {
+ public:
+ TestAImpl(ApplicationImpl* app_impl,
+ TesterContext* test_context,
+ InterfaceRequest<TestA> request)
+ : test_context_(test_context), binding_(this, request.Pass()) {
+ app_impl->ConnectToApplication(kTestBURLString)->ConnectToService(&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()->Quit();
+ test_context_->set_a_called_quit();
+ test_context_->QuitSoon();
+ }
+
+ TesterContext* test_context_;
+ TestBPtr b_;
+ StrongBinding<TestA> binding_;
+};
+
+class TestBImpl : public TestB {
+ public:
+ TestBImpl(ApplicationConnection* connection,
+ TesterContext* test_context,
+ InterfaceRequest<TestB> request)
+ : test_context_(test_context), binding_(this, request.Pass()) {
+ connection->ConnectToService(&c_);
+ }
+
+ ~TestBImpl() override {
+ test_context_->IncrementNumBDeletes();
+ if (base::MessageLoop::current()->is_running())
+ base::MessageLoop::current()->Quit();
+ 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(ApplicationConnection* connection,
+ TesterContext* test_context,
+ InterfaceRequest<TestC> request)
+ : test_context_(test_context), binding_(this, request.Pass()) {}
+
+ ~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 ApplicationDelegate,
+ public ApplicationLoader,
+ public InterfaceFactory<TestA>,
+ public InterfaceFactory<TestB>,
+ public InterfaceFactory<TestC> {
+ public:
+ Tester(TesterContext* context, const std::string& requestor_url)
+ : context_(context), requestor_url_(requestor_url) {}
+ ~Tester() override {}
+
+ private:
+ void Load(const GURL& url,
+ InterfaceRequest<Application> application_request) override {
+ app_.reset(new ApplicationImpl(this, application_request.Pass()));
+ }
+
+ bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
+ if (!requestor_url_.empty() &&
+ requestor_url_ != connection->GetRemoteApplicationURL()) {
+ context_->set_tester_called_quit();
+ context_->QuitSoon();
+ base::MessageLoop::current()->Quit();
+ return false;
+ }
+ // If we're coming from A, then add B, otherwise A.
+ if (connection->GetRemoteApplicationURL() == kTestAURLString)
+ connection->AddService<TestB>(this);
+ else
+ connection->AddService<TestA>(this);
+ return true;
+ }
+
+ bool ConfigureOutgoingConnection(ApplicationConnection* connection) override {
+ // If we're connecting to B, then add C.
+ if (connection->GetRemoteApplicationURL() == kTestBURLString)
+ connection->AddService<TestC>(this);
+ return true;
+ }
+
+ void Create(ApplicationConnection* connection,
+ InterfaceRequest<TestA> request) override {
+ a_bindings_.push_back(new TestAImpl(app_.get(), context_, request.Pass()));
+ }
+
+ void Create(ApplicationConnection* connection,
+ InterfaceRequest<TestB> request) override {
+ new TestBImpl(connection, context_, request.Pass());
+ }
+
+ void Create(ApplicationConnection* connection,
+ InterfaceRequest<TestC> request) override {
+ new TestCImpl(connection, context_, request.Pass());
+ }
+
+ TesterContext* context_;
+ scoped_ptr<ApplicationImpl> app_;
+ std::string requestor_url_;
+ ScopedVector<TestAImpl> a_bindings_;
+};
+
+class TestDelegate : public ApplicationManager::Delegate {
+ public:
+ void AddMapping(const GURL& from, const GURL& to) { mappings_[from] = to; }
+
+ // ApplicationManager::Delegate
+ GURL ResolveMappings(const GURL& url) override {
+ auto it = mappings_.find(url);
+ if (it != mappings_.end())
+ return it->second;
+ return url;
+ }
+
+ // ApplicationManager::Delegate
+ GURL ResolveURL(const GURL& url) override {
+ GURL mapped_url = ResolveMappings(url);
+ // The shell automatically map mojo URLs.
+ if (mapped_url.scheme() == "mojo") {
+ url::Replacements<char> replacements;
+ replacements.SetScheme("file", url::Component(0, 4));
+ mapped_url = mapped_url.ReplaceComponents(replacements);
+ }
+ return mapped_url;
+ }
+
+ private:
+ std::map<GURL, GURL> mappings_;
+};
+
+class TestExternal : public ApplicationDelegate {
+ public:
+ TestExternal() : configure_incoming_connection_called_(false) {}
+
+ void Initialize(ApplicationImpl* app) override {
+ initialize_args_ = app->args();
+ base::MessageLoop::current()->Quit();
+ }
+
+ bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
+ configure_incoming_connection_called_ = true;
+ base::MessageLoop::current()->Quit();
+ return true;
+ }
+
+ const std::vector<std::string>& initialize_args() const {
+ return initialize_args_;
+ }
+
+ bool configure_incoming_connection_called() const {
+ return configure_incoming_connection_called_;
+ }
+
+ private:
+ std::vector<std::string> initialize_args_;
+ bool configure_incoming_connection_called_;
+};
+
+class ApplicationManagerTest : public testing::Test {
+ public:
+ ApplicationManagerTest() : tester_context_(&loop_) {}
+
+ ~ApplicationManagerTest() override {}
+
+ void SetUp() override {
+ application_manager_.reset(new ApplicationManager(&test_delegate_));
+ test_loader_ = new TestApplicationLoader;
+ test_loader_->set_context(&context_);
+ application_manager_->set_default_loader(
+ scoped_ptr<ApplicationLoader>(test_loader_));
+
+ TestServicePtr service_proxy;
+ application_manager_->ConnectToService(GURL(kTestURLString),
+ &service_proxy);
+ test_client_.reset(new TestClient(service_proxy.Pass()));
+ }
+
+ void TearDown() override {
+ test_client_.reset();
+ application_manager_.reset();
+ }
+
+ void AddLoaderForURL(const GURL& url, const std::string& requestor_url) {
+ application_manager_->SetLoaderForURL(
+ make_scoped_ptr(new Tester(&tester_context_, requestor_url)), url);
+ }
+
+ bool HasFactoryForTestURL() {
+ ApplicationManager::TestAPI manager_test_api(application_manager_.get());
+ return manager_test_api.HasFactoryForURL(GURL(kTestURLString));
+ }
+
+ protected:
+ base::ShadowingAtExitManager at_exit_;
+ TestDelegate test_delegate_;
+ TestApplicationLoader* test_loader_;
+ TesterContext tester_context_;
+ TestContext context_;
+ base::MessageLoop loop_;
+ scoped_ptr<TestClient> test_client_;
+ scoped_ptr<ApplicationManager> application_manager_;
+ DISALLOW_COPY_AND_ASSIGN(ApplicationManagerTest);
+};
+
+TEST_F(ApplicationManagerTest, Basic) {
+ test_client_->Test("test");
+ loop_.Run();
+ EXPECT_EQ(std::string("test"), context_.last_test_string);
+}
+
+// Confirm that no arguments are sent to an application by default.
+TEST_F(ApplicationManagerTest, NoArgs) {
+ ApplicationManager am(&test_delegate_);
+ GURL test_url("test:test");
+ TestApplicationLoader* loader = new TestApplicationLoader;
+ loader->set_context(&context_);
+ am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url);
+ TestServicePtr test_service;
+ am.ConnectToService(test_url, &test_service);
+ TestClient test_client(test_service.Pass());
+ test_client.Test("test");
+ loop_.Run();
+ std::vector<std::string> app_args = loader->GetArgs();
+ EXPECT_EQ(0U, app_args.size());
+}
+
+// Confirm that arguments are sent to an application.
+TEST_F(ApplicationManagerTest, Args) {
+ ApplicationManager am(&test_delegate_);
+ GURL test_url("test:test");
+ std::vector<std::string> args;
+ args.push_back("test_arg1");
+ args.push_back("test_arg2");
+ am.SetArgsForURL(args, test_url);
+ TestApplicationLoader* loader = new TestApplicationLoader;
+ loader->set_context(&context_);
+ am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url);
+ TestServicePtr test_service;
+ am.ConnectToService(test_url, &test_service);
+ TestClient test_client(test_service.Pass());
+ test_client.Test("test");
+ loop_.Run();
+ std::vector<std::string> app_args = loader->GetArgs();
+ ASSERT_EQ(args.size(), app_args.size());
+ EXPECT_EQ(args[0], app_args[0]);
+ EXPECT_EQ(args[1], app_args[1]);
+}
+
+// Confirm that arguments are aggregated through mappings.
+TEST_F(ApplicationManagerTest, ArgsAndMapping) {
+ ApplicationManager am(&test_delegate_);
+ GURL test_url("test:test");
+ GURL test_url2("test:test2");
+ test_delegate_.AddMapping(test_url, test_url2);
+ std::vector<std::string> args;
+ args.push_back("test_arg1");
+ args.push_back("test_arg2");
+ am.SetArgsForURL(args, test_url);
+ std::vector<std::string> args2;
+ args2.push_back("test_arg3");
+ args2.push_back("test_arg4");
+ am.SetArgsForURL(args2, test_url2);
+ TestApplicationLoader* loader = new TestApplicationLoader;
+ loader->set_context(&context_);
+ am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url2);
+ {
+ // Connext to the mapped url
+ TestServicePtr test_service;
+ am.ConnectToService(test_url, &test_service);
+ TestClient test_client(test_service.Pass());
+ test_client.Test("test");
+ loop_.Run();
+ std::vector<std::string> app_args = loader->GetArgs();
+ ASSERT_EQ(args.size() + args2.size(), app_args.size());
+ EXPECT_EQ(args[0], app_args[0]);
+ EXPECT_EQ(args[1], app_args[1]);
+ EXPECT_EQ(args2[0], app_args[2]);
+ EXPECT_EQ(args2[1], app_args[3]);
+ }
+ {
+ // Connext to the target url
+ TestServicePtr test_service;
+ am.ConnectToService(test_url2, &test_service);
+ TestClient test_client(test_service.Pass());
+ test_client.Test("test");
+ loop_.Run();
+ std::vector<std::string> app_args = loader->GetArgs();
+ ASSERT_EQ(args.size() + args2.size(), app_args.size());
+ EXPECT_EQ(args[0], app_args[0]);
+ EXPECT_EQ(args[1], app_args[1]);
+ EXPECT_EQ(args2[0], app_args[2]);
+ EXPECT_EQ(args2[1], app_args[3]);
+ }
+}
+
+TEST_F(ApplicationManagerTest, ClientError) {
+ test_client_->Test("test");
+ EXPECT_TRUE(HasFactoryForTestURL());
+ loop_.Run();
+ EXPECT_EQ(1, context_.num_impls);
+ test_client_.reset();
+ loop_.Run();
+ EXPECT_EQ(0, context_.num_impls);
+ EXPECT_TRUE(HasFactoryForTestURL());
+}
+
+TEST_F(ApplicationManagerTest, Deletes) {
+ {
+ ApplicationManager am(&test_delegate_);
+ TestApplicationLoader* default_loader = new TestApplicationLoader;
+ default_loader->set_context(&context_);
+ TestApplicationLoader* url_loader1 = new TestApplicationLoader;
+ TestApplicationLoader* url_loader2 = new TestApplicationLoader;
+ url_loader1->set_context(&context_);
+ url_loader2->set_context(&context_);
+ TestApplicationLoader* scheme_loader1 = new TestApplicationLoader;
+ TestApplicationLoader* scheme_loader2 = new TestApplicationLoader;
+ scheme_loader1->set_context(&context_);
+ scheme_loader2->set_context(&context_);
+ am.set_default_loader(scoped_ptr<ApplicationLoader>(default_loader));
+ am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader1),
+ GURL("test:test1"));
+ am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader2),
+ GURL("test:test1"));
+ am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader1),
+ "test");
+ am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader2),
+ "test");
+ }
+ EXPECT_EQ(5, context_.num_loader_deletes);
+}
+
+// Confirm that both urls and schemes can have their loaders explicitly set.
+TEST_F(ApplicationManagerTest, SetLoaders) {
+ TestApplicationLoader* default_loader = new TestApplicationLoader;
+ TestApplicationLoader* url_loader = new TestApplicationLoader;
+ TestApplicationLoader* scheme_loader = new TestApplicationLoader;
+ application_manager_->set_default_loader(
+ scoped_ptr<ApplicationLoader>(default_loader));
+ application_manager_->SetLoaderForURL(
+ scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1"));
+ application_manager_->SetLoaderForScheme(
+ scoped_ptr<ApplicationLoader>(scheme_loader), "test");
+
+ // test::test1 should go to url_loader.
+ TestServicePtr test_service;
+ application_manager_->ConnectToService(GURL("test:test1"), &test_service);
+ EXPECT_EQ(1, url_loader->num_loads());
+ EXPECT_EQ(0, scheme_loader->num_loads());
+ EXPECT_EQ(0, default_loader->num_loads());
+
+ // test::test2 should go to scheme loader.
+ application_manager_->ConnectToService(GURL("test:test2"), &test_service);
+ EXPECT_EQ(1, url_loader->num_loads());
+ EXPECT_EQ(1, scheme_loader->num_loads());
+ EXPECT_EQ(0, default_loader->num_loads());
+
+ // http::test1 should go to default loader.
+ application_manager_->ConnectToService(GURL("http:test1"), &test_service);
+ EXPECT_EQ(1, url_loader->num_loads());
+ EXPECT_EQ(1, scheme_loader->num_loads());
+ EXPECT_EQ(1, default_loader->num_loads());
+}
+
+// Confirm that the url of a service is correctly passed to another service that
+// it loads.
+TEST_F(ApplicationManagerTest, ACallB) {
+ // Any url can load a.
+ AddLoaderForURL(GURL(kTestAURLString), std::string());
+
+ // Only a can load b.
+ AddLoaderForURL(GURL(kTestBURLString), kTestAURLString);
+
+ TestAPtr a;
+ application_manager_->ConnectToService(GURL(kTestAURLString), &a);
+ a->CallB();
+ loop_.Run();
+ EXPECT_EQ(1, tester_context_.num_b_calls());
+ EXPECT_TRUE(tester_context_.a_called_quit());
+}
+
+// A calls B which calls C.
+TEST_F(ApplicationManagerTest, BCallC) {
+ // Any url can load a.
+ AddLoaderForURL(GURL(kTestAURLString), std::string());
+
+ // Only a can load b.
+ AddLoaderForURL(GURL(kTestBURLString), kTestAURLString);
+
+ TestAPtr a;
+ application_manager_->ConnectToService(GURL(kTestAURLString), &a);
+ a->CallCFromB();
+ loop_.Run();
+
+ EXPECT_EQ(1, tester_context_.num_b_calls());
+ EXPECT_EQ(1, tester_context_.num_c_calls());
+ EXPECT_TRUE(tester_context_.a_called_quit());
+}
+
+// Confirm that a service impl will be deleted if the app that connected to
+// it goes away.
+TEST_F(ApplicationManagerTest, BDeleted) {
+ AddLoaderForURL(GURL(kTestAURLString), std::string());
+ AddLoaderForURL(GURL(kTestBURLString), std::string());
+
+ TestAPtr a;
+ application_manager_->ConnectToService(GURL(kTestAURLString), &a);
+
+ a->CallB();
+ loop_.Run();
+
+ // Kills the a app.
+ application_manager_->SetLoaderForURL(scoped_ptr<ApplicationLoader>(),
+ GURL(kTestAURLString));
+ loop_.Run();
+
+ EXPECT_EQ(1, tester_context_.num_b_deletes());
+}
+
+// Confirm that the url of a service is correctly passed to another service that
+// it loads, and that it can be rejected.
+TEST_F(ApplicationManagerTest, ANoLoadB) {
+ // Any url can load a.
+ AddLoaderForURL(GURL(kTestAURLString), std::string());
+
+ // Only c can load b, so this will fail.
+ AddLoaderForURL(GURL(kTestBURLString), "test:TestC");
+
+ TestAPtr a;
+ application_manager_->ConnectToService(GURL(kTestAURLString), &a);
+ a->CallB();
+ loop_.Run();
+ EXPECT_EQ(0, tester_context_.num_b_calls());
+
+ EXPECT_FALSE(tester_context_.a_called_quit());
+ EXPECT_TRUE(tester_context_.tester_called_quit());
+}
+
+TEST_F(ApplicationManagerTest, NoServiceNoLoad) {
+ AddLoaderForURL(GURL(kTestAURLString), std::string());
+
+ // There is no TestC service implementation registered with
+ // ApplicationManager, so this cannot succeed (but also shouldn't crash).
+ TestCPtr c;
+ application_manager_->ConnectToService(GURL(kTestAURLString), &c);
+ QuitMessageLoopErrorHandler quitter;
+ c.set_error_handler(&quitter);
+
+ loop_.Run();
+ EXPECT_TRUE(c.encountered_error());
+}
+
+TEST_F(ApplicationManagerTest, MappedURLsShouldNotCauseDuplicateLoad) {
+ test_delegate_.AddMapping(GURL("foo:foo2"), GURL("foo:foo"));
+ // 1 because ApplicationManagerTest connects once at startup.
+ EXPECT_EQ(1, test_loader_->num_loads());
+
+ TestServicePtr test_service;
+ application_manager_->ConnectToService(GURL("foo:foo"), &test_service);
+ EXPECT_EQ(2, test_loader_->num_loads());
+
+ TestServicePtr test_service2;
+ application_manager_->ConnectToService(GURL("foo:foo2"), &test_service2);
+ EXPECT_EQ(2, test_loader_->num_loads());
+
+ TestServicePtr test_service3;
+ application_manager_->ConnectToService(GURL("bar:bar"), &test_service2);
+ EXPECT_EQ(3, test_loader_->num_loads());
+}
+
+TEST_F(ApplicationManagerTest, MappedURLsShouldWorkWithLoaders) {
+ TestApplicationLoader* custom_loader = new TestApplicationLoader;
+ TestContext context;
+ custom_loader->set_context(&context);
+ application_manager_->SetLoaderForURL(make_scoped_ptr(custom_loader),
+ GURL("mojo:foo"));
+ test_delegate_.AddMapping(GURL("mojo:foo2"), GURL("mojo:foo"));
+
+ TestServicePtr test_service;
+ application_manager_->ConnectToService(GURL("mojo:foo2"), &test_service);
+ EXPECT_EQ(1, custom_loader->num_loads());
+ custom_loader->set_context(nullptr);
+}
+
+TEST_F(ApplicationManagerTest, ExternalApp) {
+ ApplicationPtr application;
+ TestExternal external;
+ std::vector<std::string> args;
+ args.push_back("test");
+ ApplicationImpl app(&external, GetProxy(&application));
+ application_manager_->RegisterExternalApplication(GURL("mojo:test"), args,
+ application.Pass());
+ loop_.Run();
+ EXPECT_EQ(args, external.initialize_args());
+ application_manager_->ConnectToServiceByName(GURL("mojo:test"),
+ std::string());
+ loop_.Run();
+ EXPECT_TRUE(external.configure_incoming_connection_called());
+};
+
+TEST_F(ApplicationManagerTest, TestQueryWithLoaders) {
+ TestApplicationLoader* url_loader = new TestApplicationLoader;
+ TestApplicationLoader* scheme_loader = new TestApplicationLoader;
+ application_manager_->SetLoaderForURL(
+ scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1"));
+ application_manager_->SetLoaderForScheme(
+ scoped_ptr<ApplicationLoader>(scheme_loader), "test");
+
+ // test::test1 should go to url_loader.
+ TestServicePtr test_service;
+ application_manager_->ConnectToService(GURL("test:test1?foo=bar"),
+ &test_service);
+ EXPECT_EQ(1, url_loader->num_loads());
+ EXPECT_EQ(0, scheme_loader->num_loads());
+
+ // test::test2 should go to scheme loader.
+ application_manager_->ConnectToService(GURL("test:test2?foo=bar"),
+ &test_service);
+ EXPECT_EQ(1, url_loader->num_loads());
+ EXPECT_EQ(1, scheme_loader->num_loads());
+}
+
+TEST_F(ApplicationManagerTest, TestEndApplicationClosure) {
+ ClosingApplicationLoader* loader = new ClosingApplicationLoader();
+ application_manager_->SetLoaderForScheme(
+ scoped_ptr<ApplicationLoader>(loader), "test");
+
+ bool called = false;
+ application_manager_->ConnectToApplication(
+ GURL("test:test"), GURL(), nullptr, nullptr,
+ base::Bind(&QuitClosure, base::Unretained(&called)));
+ loop_.Run();
+ EXPECT_TRUE(called);
+}
+
+} // namespace
+} // namespace shell
+} // namespace mojo
« no previous file with comments | « mojo/shell/application_manager/application_manager.cc ('k') | mojo/shell/application_manager/data_pipe_peek.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698