Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / mojo / service_manager / service_manager_unittest.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/message_loop/message_loop.h"
6 #include "mojo/public/cpp/bindings/allocation_scope.h"
7 #include "mojo/public/cpp/environment/environment.h"
8 #include "mojo/public/cpp/shell/application.h"
9 #include "mojo/public/interfaces/shell/shell.mojom.h"
10 #include "mojo/service_manager/service_loader.h"
11 #include "mojo/service_manager/service_manager.h"
12 #include "mojo/service_manager/test.mojom.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace mojo {
16 namespace {
17
18 const char kTestURLString[] = "test:testService";
19
20 struct TestContext {
21   TestContext() : num_impls(0), num_loader_deletes(0) {}
22   std::string last_test_string;
23   int num_impls;
24   int num_loader_deletes;
25 };
26
27 class TestServiceImpl :
28     public ServiceConnection<TestService, TestServiceImpl, TestContext> {
29  public:
30   TestServiceImpl() : client_(NULL) {}
31
32   virtual ~TestServiceImpl() {
33     if (context())
34       --context()->num_impls;
35   }
36
37   void Initialize() {
38     if (context())
39       ++context()->num_impls;
40   }
41
42   // TestService implementation:
43   virtual void SetClient(TestClient* client) OVERRIDE {
44     client_ = client;
45   }
46   virtual void Test(const mojo::String& test_string) OVERRIDE {
47     context()->last_test_string = test_string.To<std::string>();
48     client_->AckTest();
49   }
50
51  private:
52   TestClient* client_;
53 };
54
55 class TestClientImpl : public TestClient {
56  public:
57   explicit TestClientImpl(TestServicePtr service)
58       : service_(service.Pass()),
59         quit_after_ack_(false) {
60     service_->SetClient(this);
61   }
62
63   virtual ~TestClientImpl() {}
64
65   virtual void AckTest() OVERRIDE {
66     if (quit_after_ack_)
67       base::MessageLoop::current()->Quit();
68   }
69
70   void Test(std::string test_string) {
71     AllocationScope scope;
72     quit_after_ack_ = true;
73     service_->Test(test_string);
74   }
75
76  private:
77   TestServicePtr service_;
78   bool quit_after_ack_;
79   DISALLOW_COPY_AND_ASSIGN(TestClientImpl);
80 };
81
82 class TestServiceLoader : public ServiceLoader {
83  public:
84   TestServiceLoader()
85       : context_(NULL),
86         num_loads_(0),
87         quit_after_error_(false) {
88   }
89
90   virtual ~TestServiceLoader() {
91     if (context_)
92       ++context_->num_loader_deletes;
93     test_app_.reset(NULL);
94   }
95
96   void set_context(TestContext* context) { context_ = context; }
97   void set_quit_after_error(bool quit_after_error) {
98     quit_after_error_ = quit_after_error;
99   }
100
101   int num_loads() const { return num_loads_; }
102
103  private:
104   virtual void LoadService(ServiceManager* manager,
105                            const GURL& url,
106                            ScopedMessagePipeHandle shell_handle) OVERRIDE {
107     ++num_loads_;
108     test_app_.reset(new Application(shell_handle.Pass()));
109     test_app_->AddServiceConnector(
110         new ServiceConnector<TestServiceImpl, TestContext>(context_));
111   }
112
113   virtual void OnServiceError(ServiceManager* manager,
114                               const GURL& url) OVERRIDE {
115     if (quit_after_error_) {
116       base::MessageLoop::current()->PostTask(FROM_HERE,
117                                              base::MessageLoop::QuitClosure());
118     }
119   }
120
121
122   scoped_ptr<Application> test_app_;
123   TestContext* context_;
124   int num_loads_;
125   bool quit_after_error_;
126   DISALLOW_COPY_AND_ASSIGN(TestServiceLoader);
127 };
128
129 class TestServiceInterceptor : public ServiceManager::Interceptor {
130  public:
131   TestServiceInterceptor() : call_count_(0) {}
132
133   virtual ScopedMessagePipeHandle OnConnectToClient(
134       const GURL& url, ScopedMessagePipeHandle handle) OVERRIDE {
135     ++call_count_;
136     url_ = url;
137     return handle.Pass();
138   }
139
140   std::string url_spec() const {
141     if (!url_.is_valid())
142       return "invalid url";
143     return url_.spec();
144   }
145
146   int call_count() const {
147     return call_count_;
148   }
149
150  private:
151   int call_count_;
152   GURL url_;
153   DISALLOW_COPY_AND_ASSIGN(TestServiceInterceptor);
154 };
155
156 }  // namespace
157
158 class ServiceManagerTest : public testing::Test {
159  public:
160   ServiceManagerTest() {}
161
162   virtual ~ServiceManagerTest() {}
163
164   virtual void SetUp() OVERRIDE {
165     GURL test_url(kTestURLString);
166     service_manager_.reset(new ServiceManager);
167
168     MessagePipe pipe;
169     TestServicePtr service_proxy = MakeProxy<TestService>(pipe.handle0.Pass());
170     test_client_.reset(new TestClientImpl(service_proxy.Pass()));
171
172     TestServiceLoader* default_loader = new TestServiceLoader;
173     default_loader->set_context(&context_);
174     default_loader->set_quit_after_error(true);
175     service_manager_->set_default_loader(
176         scoped_ptr<ServiceLoader>(default_loader));
177
178     service_manager_->Connect(test_url, pipe.handle1.Pass());
179   }
180
181   virtual void TearDown() OVERRIDE {
182     test_client_.reset(NULL);
183     service_manager_.reset(NULL);
184   }
185
186   bool HasFactoryForTestURL() {
187     ServiceManager::TestAPI manager_test_api(service_manager_.get());
188     return manager_test_api.HasFactoryForURL(GURL(kTestURLString));
189   }
190
191  protected:
192   mojo::Environment env_;
193   base::MessageLoop loop_;
194   TestContext context_;
195   scoped_ptr<TestClientImpl> test_client_;
196   scoped_ptr<ServiceManager> service_manager_;
197   DISALLOW_COPY_AND_ASSIGN(ServiceManagerTest);
198 };
199
200 TEST_F(ServiceManagerTest, Basic) {
201   test_client_->Test("test");
202   loop_.Run();
203   EXPECT_EQ(std::string("test"), context_.last_test_string);
204 }
205
206 TEST_F(ServiceManagerTest, ClientError) {
207   test_client_->Test("test");
208   EXPECT_TRUE(HasFactoryForTestURL());
209   loop_.Run();
210   EXPECT_EQ(1, context_.num_impls);
211   test_client_.reset(NULL);
212   loop_.Run();
213   EXPECT_EQ(0, context_.num_impls);
214   EXPECT_FALSE(HasFactoryForTestURL());
215 }
216
217 TEST_F(ServiceManagerTest, Deletes) {
218   {
219     ServiceManager sm;
220     TestServiceLoader* default_loader = new TestServiceLoader;
221     default_loader->set_context(&context_);
222     TestServiceLoader* url_loader1 = new TestServiceLoader;
223     TestServiceLoader* url_loader2 = new TestServiceLoader;
224     url_loader1->set_context(&context_);
225     url_loader2->set_context(&context_);
226     TestServiceLoader* scheme_loader1 = new TestServiceLoader;
227     TestServiceLoader* scheme_loader2 = new TestServiceLoader;
228     scheme_loader1->set_context(&context_);
229     scheme_loader2->set_context(&context_);
230     sm.set_default_loader(scoped_ptr<ServiceLoader>(default_loader));
231     sm.SetLoaderForURL(scoped_ptr<ServiceLoader>(url_loader1),
232                        GURL("test:test1"));
233     sm.SetLoaderForURL(scoped_ptr<ServiceLoader>(url_loader2),
234                        GURL("test:test1"));
235     sm.SetLoaderForScheme(scoped_ptr<ServiceLoader>(scheme_loader1), "test");
236     sm.SetLoaderForScheme(scoped_ptr<ServiceLoader>(scheme_loader2), "test");
237   }
238   EXPECT_EQ(5, context_.num_loader_deletes);
239 }
240
241 // Confirm that both urls and schemes can have their loaders explicitly set.
242 TEST_F(ServiceManagerTest, SetLoaders) {
243   ServiceManager sm;
244   TestServiceLoader* default_loader = new TestServiceLoader;
245   TestServiceLoader* url_loader = new TestServiceLoader;
246   TestServiceLoader* scheme_loader = new TestServiceLoader;
247   sm.set_default_loader(scoped_ptr<ServiceLoader>(default_loader));
248   sm.SetLoaderForURL(scoped_ptr<ServiceLoader>(url_loader), GURL("test:test1"));
249   sm.SetLoaderForScheme(scoped_ptr<ServiceLoader>(scheme_loader), "test");
250
251   // test::test1 should go to url_loader.
252   MessagePipe pipe1;
253   sm.Connect(GURL("test:test1"), pipe1.handle0.Pass());
254   EXPECT_EQ(1, url_loader->num_loads());
255   EXPECT_EQ(0, scheme_loader->num_loads());
256   EXPECT_EQ(0, default_loader->num_loads());
257
258   // test::test2 should go to scheme loader.
259   MessagePipe pipe2;
260   sm.Connect(GURL("test:test2"), pipe2.handle0.Pass());
261   EXPECT_EQ(1, url_loader->num_loads());
262   EXPECT_EQ(1, scheme_loader->num_loads());
263   EXPECT_EQ(0, default_loader->num_loads());
264
265   // http::test1 should go to default loader.
266   MessagePipe pipe3;
267   sm.Connect(GURL("http:test1"), pipe3.handle0.Pass());
268   EXPECT_EQ(1, url_loader->num_loads());
269   EXPECT_EQ(1, scheme_loader->num_loads());
270   EXPECT_EQ(1, default_loader->num_loads());
271 }
272
273 TEST_F(ServiceManagerTest, Interceptor) {
274   ServiceManager sm;
275   TestServiceInterceptor interceptor;
276   TestServiceLoader* default_loader = new TestServiceLoader;
277   sm.set_default_loader(scoped_ptr<ServiceLoader>(default_loader));
278   sm.SetInterceptor(&interceptor);
279
280   std::string url("test:test3");
281   MessagePipe pipe1;
282   sm.Connect(GURL(url), pipe1.handle0.Pass());
283   EXPECT_EQ(1, interceptor.call_count());
284   EXPECT_EQ(url, interceptor.url_spec());
285   EXPECT_EQ(1, default_loader->num_loads());
286 }
287
288 }  // namespace mojo