Load apps on separate threads in service_manager_unittests
This loads up and destroys applications on their own thread (using
BackgroundServiceLoader) so we can test the full in-process application
lifecycle.
BUG=396300
Review URL: https://codereview.chromium.org/415803005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285410 0039d316-1c4b-4281-b951-d872f2087c98
CrOS-Libchrome-Original-Commit: 121063d342c5ca5432268dbbb4ba98691f3b7804
diff --git a/mojo/service_manager/service_manager_unittest.cc b/mojo/service_manager/service_manager_unittest.cc
index a42dc5f..b1abb79 100644
--- a/mojo/service_manager/service_manager_unittest.cc
+++ b/mojo/service_manager/service_manager_unittest.cc
@@ -10,6 +10,7 @@
#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
+#include "mojo/service_manager/background_service_loader.h"
#include "mojo/service_manager/service_loader.h"
#include "mojo/service_manager/service_manager.h"
#include "mojo/service_manager/test.mojom.h"
@@ -148,22 +149,99 @@
DISALLOW_COPY_AND_ASSIGN(TestServiceLoader);
};
-struct TesterContext {
- TesterContext()
- : 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) {}
- 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;
+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.
@@ -173,7 +251,7 @@
: test_context_(test_context) {
connection->ConnectToApplication(kTestBURLString)->ConnectToService(&b_);
}
- virtual ~TestAImpl() { test_context_->num_a_deletes++; }
+ virtual ~TestAImpl() { test_context_->IncrementNumADeletes(); }
private:
virtual void CallB() OVERRIDE {
@@ -185,8 +263,8 @@
}
void Quit() {
- test_context_->a_called_quit = true;
- base::MessageLoop::current()->Quit();
+ test_context_->set_a_called_quit();
+ test_context_->QuitSoon();
}
TesterContext* test_context_;
@@ -201,20 +279,18 @@
}
virtual ~TestBImpl() {
- test_context_->num_b_deletes++;
- if (!base::MessageLoop::current()->is_running())
- return;
- base::MessageLoop::current()->Quit();
+ test_context_->IncrementNumBDeletes();
+ test_context_->QuitSoon();
}
private:
virtual void B(const mojo::Callback<void()>& callback) OVERRIDE {
- ++test_context_->num_b_calls;
+ test_context_->IncrementNumBCalls();
callback.Run();
}
virtual void CallC(const mojo::Callback<void()>& callback) OVERRIDE {
- ++test_context_->num_b_calls;
+ test_context_->IncrementNumBCalls();
c_->C(callback);
}
@@ -227,11 +303,11 @@
TestCImpl(ApplicationConnection* connection, TesterContext* test_context)
: test_context_(test_context) {}
- virtual ~TestCImpl() { test_context_->num_c_deletes++; }
+ virtual ~TestCImpl() { test_context_->IncrementNumCDeletes(); }
private:
virtual void C(const mojo::Callback<void()>& callback) OVERRIDE {
- ++test_context_->num_c_calls;
+ test_context_->IncrementNumCCalls();
callback.Run();
}
TesterContext* test_context_;
@@ -263,8 +339,8 @@
ApplicationConnection* connection) OVERRIDE {
if (!requestor_url_.empty() &&
requestor_url_ != connection->GetRemoteApplicationURL()) {
- context_->tester_called_quit = true;
- base::MessageLoop::current()->Quit();
+ context_->set_tester_called_quit();
+ context_->QuitSoon();
return false;
}
// If we're coming from A, then add B, otherwise A.
@@ -334,7 +410,7 @@
class ServiceManagerTest : public testing::Test {
public:
- ServiceManagerTest() {}
+ ServiceManagerTest() : tester_context_(&loop_) {}
virtual ~ServiceManagerTest() {}
@@ -355,6 +431,15 @@
service_manager_.reset(NULL);
}
+ void AddLoaderForURL(const GURL& url, const std::string& requestor_url) {
+ scoped_ptr<ServiceLoader> real_loader(
+ new Tester(&tester_context_, requestor_url));
+ service_manager_->SetLoaderForURL(
+ scoped_ptr<ServiceLoader>(new BackgroundServiceLoader(
+ real_loader.Pass(), "", base::MessageLoop::TYPE_DEFAULT)),
+ url);
+ }
+
bool HasFactoryForTestURL() {
ServiceManager::TestAPI manager_test_api(service_manager_.get());
return manager_test_api.HasFactoryForURL(GURL(kTestURLString));
@@ -362,8 +447,9 @@
protected:
base::ShadowingAtExitManager at_exit_;
- base::MessageLoop loop_;
+ TesterContext tester_context_;
TestContext context_;
+ base::MessageLoop loop_;
scoped_ptr<TestClientImpl> test_client_;
scoped_ptr<ServiceManager> service_manager_;
DISALLOW_COPY_AND_ASSIGN(ServiceManagerTest);
@@ -416,25 +502,28 @@
TestServiceLoader* default_loader = new TestServiceLoader;
TestServiceLoader* url_loader = new TestServiceLoader;
TestServiceLoader* scheme_loader = new TestServiceLoader;
- sm.set_default_loader(scoped_ptr<ServiceLoader>(default_loader));
- sm.SetLoaderForURL(scoped_ptr<ServiceLoader>(url_loader), GURL("test:test1"));
- sm.SetLoaderForScheme(scoped_ptr<ServiceLoader>(scheme_loader), "test");
+ service_manager_->set_default_loader(
+ scoped_ptr<ServiceLoader>(default_loader));
+ service_manager_->SetLoaderForURL(scoped_ptr<ServiceLoader>(url_loader),
+ GURL("test:test1"));
+ service_manager_->SetLoaderForScheme(scoped_ptr<ServiceLoader>(scheme_loader),
+ "test");
// test::test1 should go to url_loader.
TestServicePtr test_service;
- sm.ConnectToService(GURL("test:test1"), &test_service);
+ service_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.
- sm.ConnectToService(GURL("test:test2"), &test_service);
+ service_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.
- sm.ConnectToService(GURL("http:test1"), &test_service);
+ service_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());
@@ -442,121 +531,83 @@
// Confirm that the url of a service is correctly passed to another service that
// it loads.
-// http://crbug.com/396300
-TEST_F(ServiceManagerTest, DISABLED_ACallB) {
- TesterContext context;
- ServiceManager sm;
-
+TEST_F(ServiceManagerTest, ACallB) {
// Any url can load a.
- sm.SetLoaderForURL(
- scoped_ptr<ServiceLoader>(new Tester(&context, std::string())),
- GURL(kTestAURLString));
+ AddLoaderForURL(GURL(kTestAURLString), std::string());
// Only a can load b.
- sm.SetLoaderForURL(
- scoped_ptr<ServiceLoader>(
- new Tester(&context, kTestAURLString)),
- GURL(kTestBURLString));
+ AddLoaderForURL(GURL(kTestBURLString), kTestAURLString);
TestAPtr a;
- sm.ConnectToService(GURL(kTestAURLString), &a);
+ service_manager_->ConnectToService(GURL(kTestAURLString), &a);
a->CallB();
loop_.Run();
- EXPECT_EQ(1, context.num_b_calls);
- EXPECT_TRUE(context.a_called_quit);
+ EXPECT_EQ(1, tester_context_.num_b_calls());
+ EXPECT_TRUE(tester_context_.a_called_quit());
}
// A calls B which calls C.
-// http://crbug.com/396300
-TEST_F(ServiceManagerTest, DISABLED_BCallC) {
- TesterContext context;
- ServiceManager sm;
-
+TEST_F(ServiceManagerTest, BCallC) {
// Any url can load a.
- sm.SetLoaderForURL(
- scoped_ptr<ServiceLoader>(new Tester(&context, std::string())),
- GURL(kTestAURLString));
+ AddLoaderForURL(GURL(kTestAURLString), std::string());
// Only a can load b.
- sm.SetLoaderForURL(
- scoped_ptr<ServiceLoader>(
- new Tester(&context, kTestAURLString)),
- GURL(kTestBURLString));
+ AddLoaderForURL(GURL(kTestBURLString), kTestAURLString);
TestAPtr a;
- sm.ConnectToService(GURL(kTestAURLString), &a);
+ service_manager_->ConnectToService(GURL(kTestAURLString), &a);
a->CallCFromB();
loop_.Run();
- EXPECT_EQ(1, context.num_b_calls);
- EXPECT_EQ(1, context.num_c_calls);
- EXPECT_TRUE(context.a_called_quit);
+ 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.
-// http://crbug.com/396300
-TEST_F(ServiceManagerTest, DISABLED_BDeleted) {
- TesterContext context;
- ServiceManager sm;
-
- sm.SetLoaderForURL(
- scoped_ptr<ServiceLoader>(new Tester(&context, std::string())),
- GURL(kTestAURLString));
-
- sm.SetLoaderForURL(
- scoped_ptr<ServiceLoader>( new Tester(&context, std::string())),
- GURL(kTestBURLString));
+TEST_F(ServiceManagerTest, BDeleted) {
+ AddLoaderForURL(GURL(kTestAURLString), std::string());
+ AddLoaderForURL(GURL(kTestBURLString), std::string());
TestAPtr a;
- sm.ConnectToService(GURL(kTestAURLString), &a);
+ service_manager_->ConnectToService(GURL(kTestAURLString), &a);
a->CallB();
loop_.Run();
// Kills the a app.
- sm.SetLoaderForURL(scoped_ptr<ServiceLoader>(), GURL(kTestAURLString));
+ service_manager_->SetLoaderForURL(scoped_ptr<ServiceLoader>(),
+ GURL(kTestAURLString));
loop_.Run();
- EXPECT_EQ(1, context.num_b_deletes);
+
+ 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.
-// http://crbug.com/396300
-TEST_F(ServiceManagerTest, DISABLED_ANoLoadB) {
- TesterContext context;
- ServiceManager sm;
-
+TEST_F(ServiceManagerTest, ANoLoadB) {
// Any url can load a.
- sm.SetLoaderForURL(
- scoped_ptr<ServiceLoader>(new Tester(&context, std::string())),
- GURL(kTestAURLString));
+ AddLoaderForURL(GURL(kTestAURLString), std::string());
// Only c can load b, so this will fail.
- sm.SetLoaderForURL(
- scoped_ptr<ServiceLoader>(new Tester(&context, "test:TestC")),
- GURL(kTestBURLString));
+ AddLoaderForURL(GURL(kTestBURLString), "test:TestC");
TestAPtr a;
- sm.ConnectToService(GURL(kTestAURLString), &a);
+ service_manager_->ConnectToService(GURL(kTestAURLString), &a);
a->CallB();
loop_.Run();
- EXPECT_EQ(0, context.num_b_calls);
- EXPECT_TRUE(context.tester_called_quit);
+ EXPECT_EQ(0, tester_context_.num_b_calls());
+ EXPECT_TRUE(tester_context_.tester_called_quit());
}
TEST_F(ServiceManagerTest, NoServiceNoLoad) {
- TesterContext context;
- ServiceManager sm;
-
- sm.SetLoaderForURL(
- scoped_ptr<ServiceLoader>(new Tester(&context, std::string())),
- GURL(kTestAURLString));
+ AddLoaderForURL(GURL(kTestAURLString), std::string());
// There is no TestC service implementation registered with ServiceManager,
// so this cannot succeed (but also shouldn't crash).
TestCPtr c;
- sm.ConnectToService(GURL(kTestAURLString), &c);
+ service_manager_->ConnectToService(GURL(kTestAURLString), &c);
QuitMessageLoopErrorHandler quitter;
c.set_error_handler(&quitter);
@@ -565,15 +616,15 @@
}
TEST_F(ServiceManagerTest, Interceptor) {
- ServiceManager sm;
TestServiceInterceptor interceptor;
TestServiceLoader* default_loader = new TestServiceLoader;
- sm.set_default_loader(scoped_ptr<ServiceLoader>(default_loader));
- sm.SetInterceptor(&interceptor);
+ service_manager_->set_default_loader(
+ scoped_ptr<ServiceLoader>(default_loader));
+ service_manager_->SetInterceptor(&interceptor);
std::string url("test:test3");
TestServicePtr test_service;
- sm.ConnectToService(GURL(url), &test_service);
+ service_manager_->ConnectToService(GURL(url), &test_service);
EXPECT_EQ(1, interceptor.call_count());
EXPECT_EQ(url, interceptor.url_spec());