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

Side by Side Diff: mojo/shell/application_manager_unittest.cc

Issue 1706833003: Move various Shell tests into a subdir. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@conn
Patch Set: . Created 4 years, 10 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 unified diff | Download patch
« no previous file with comments | « mojo/shell/application_manager_apptests.mojom ('k') | mojo/shell/capability_filter_test.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "mojo/shell/application_manager.h"
6
7 #include <utility>
8
9 #include "base/at_exit.h"
10 #include "base/bind.h"
11 #include "base/macros.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/run_loop.h"
15 #include "mojo/public/cpp/bindings/strong_binding.h"
16 #include "mojo/shell/application_loader.h"
17 #include "mojo/shell/connect_util.h"
18 #include "mojo/shell/public/cpp/interface_factory.h"
19 #include "mojo/shell/public/cpp/shell_client.h"
20 #include "mojo/shell/public/cpp/shell_connection.h"
21 #include "mojo/shell/public/interfaces/interface_provider.mojom.h"
22 #include "mojo/shell/test.mojom.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 namespace mojo {
26 namespace shell {
27 namespace test {
28
29 const char kTestURLString[] = "test:testService";
30 const char kTestAURLString[] = "test:TestA";
31 const char kTestBURLString[] = "test:TestB";
32
33 struct TestContext {
34 TestContext() : num_impls(0), num_loader_deletes(0) {}
35 std::string last_test_string;
36 int num_impls;
37 int num_loader_deletes;
38 };
39
40 void QuitClosure(bool* value) {
41 *value = true;
42 base::MessageLoop::current()->QuitWhenIdle();
43 }
44
45 class TestServiceImpl : public TestService {
46 public:
47 TestServiceImpl(TestContext* context, InterfaceRequest<TestService> request)
48 : context_(context), binding_(this, std::move(request)) {
49 ++context_->num_impls;
50 }
51
52 ~TestServiceImpl() override {
53 --context_->num_impls;
54 if (!base::MessageLoop::current()->is_running())
55 return;
56 base::MessageLoop::current()->QuitWhenIdle();
57 }
58
59 // TestService implementation:
60 void Test(const String& test_string,
61 const Callback<void()>& callback) override {
62 context_->last_test_string = test_string;
63 callback.Run();
64 }
65
66 private:
67 TestContext* context_;
68 StrongBinding<TestService> binding_;
69 };
70
71 class TestClient {
72 public:
73 explicit TestClient(TestServicePtr service)
74 : service_(std::move(service)), quit_after_ack_(false) {}
75
76 void AckTest() {
77 if (quit_after_ack_)
78 base::MessageLoop::current()->QuitWhenIdle();
79 }
80
81 void Test(const std::string& test_string) {
82 quit_after_ack_ = true;
83 service_->Test(test_string,
84 base::Bind(&TestClient::AckTest, base::Unretained(this)));
85 }
86
87 private:
88 TestServicePtr service_;
89 bool quit_after_ack_;
90 DISALLOW_COPY_AND_ASSIGN(TestClient);
91 };
92
93 class TestApplicationLoader : public ApplicationLoader,
94 public ShellClient,
95 public InterfaceFactory<TestService> {
96 public:
97 TestApplicationLoader()
98 : context_(nullptr), num_loads_(0) {}
99
100 ~TestApplicationLoader() override {
101 if (context_)
102 ++context_->num_loader_deletes;
103 shell_connection_.reset();
104 }
105
106 void set_context(TestContext* context) { context_ = context; }
107 int num_loads() const { return num_loads_; }
108 const GURL& last_requestor_url() const { return last_requestor_url_; }
109
110 private:
111 // ApplicationLoader implementation.
112 void Load(const GURL& url,
113 InterfaceRequest<mojom::ShellClient> request) override {
114 ++num_loads_;
115 shell_connection_.reset(new ShellConnection(this, std::move(request)));
116 }
117
118 // mojo::ShellClient implementation.
119 bool AcceptConnection(Connection* connection) override {
120 connection->AddInterface<TestService>(this);
121 last_requestor_url_ = GURL(connection->GetRemoteApplicationURL());
122 return true;
123 }
124
125 // InterfaceFactory<TestService> implementation.
126 void Create(Connection* connection,
127 InterfaceRequest<TestService> request) override {
128 new TestServiceImpl(context_, std::move(request));
129 }
130
131 scoped_ptr<ShellConnection> shell_connection_;
132 TestContext* context_;
133 int num_loads_;
134 GURL last_requestor_url_;
135
136 DISALLOW_COPY_AND_ASSIGN(TestApplicationLoader);
137 };
138
139 class ClosingApplicationLoader : public ApplicationLoader {
140 private:
141 // ApplicationLoader implementation.
142 void Load(const GURL& url,
143 InterfaceRequest<mojom::ShellClient> request) override {
144 }
145 };
146
147 class TesterContext {
148 public:
149 explicit TesterContext(base::MessageLoop* loop)
150 : num_b_calls_(0),
151 num_c_calls_(0),
152 num_a_deletes_(0),
153 num_b_deletes_(0),
154 num_c_deletes_(0),
155 tester_called_quit_(false),
156 a_called_quit_(false),
157 loop_(loop) {}
158
159 void IncrementNumBCalls() {
160 base::AutoLock lock(lock_);
161 num_b_calls_++;
162 }
163
164 void IncrementNumCCalls() {
165 base::AutoLock lock(lock_);
166 num_c_calls_++;
167 }
168
169 void IncrementNumADeletes() {
170 base::AutoLock lock(lock_);
171 num_a_deletes_++;
172 }
173
174 void IncrementNumBDeletes() {
175 base::AutoLock lock(lock_);
176 num_b_deletes_++;
177 }
178
179 void IncrementNumCDeletes() {
180 base::AutoLock lock(lock_);
181 num_c_deletes_++;
182 }
183
184 void set_tester_called_quit() {
185 base::AutoLock lock(lock_);
186 tester_called_quit_ = true;
187 }
188
189 void set_a_called_quit() {
190 base::AutoLock lock(lock_);
191 a_called_quit_ = true;
192 }
193
194 int num_b_calls() {
195 base::AutoLock lock(lock_);
196 return num_b_calls_;
197 }
198 int num_c_calls() {
199 base::AutoLock lock(lock_);
200 return num_c_calls_;
201 }
202 int num_a_deletes() {
203 base::AutoLock lock(lock_);
204 return num_a_deletes_;
205 }
206 int num_b_deletes() {
207 base::AutoLock lock(lock_);
208 return num_b_deletes_;
209 }
210 int num_c_deletes() {
211 base::AutoLock lock(lock_);
212 return num_c_deletes_;
213 }
214 bool tester_called_quit() {
215 base::AutoLock lock(lock_);
216 return tester_called_quit_;
217 }
218 bool a_called_quit() {
219 base::AutoLock lock(lock_);
220 return a_called_quit_;
221 }
222
223 void QuitSoon() {
224 loop_->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
225 }
226
227 private:
228 // lock_ protects all members except for loop_ which must be unchanged for the
229 // lifetime of this class.
230 base::Lock lock_;
231 int num_b_calls_;
232 int num_c_calls_;
233 int num_a_deletes_;
234 int num_b_deletes_;
235 int num_c_deletes_;
236 bool tester_called_quit_;
237 bool a_called_quit_;
238
239 base::MessageLoop* loop_;
240 };
241
242 // Used to test that the requestor url will be correctly passed.
243 class TestAImpl : public TestA {
244 public:
245 TestAImpl(Shell* shell,
246 TesterContext* test_context,
247 InterfaceRequest<TestA> request,
248 InterfaceFactory<TestC>* factory)
249 : test_context_(test_context), binding_(this, std::move(request)) {
250 connection_ = shell->Connect(kTestBURLString);
251 connection_->AddInterface<TestC>(factory);
252 connection_->GetInterface(&b_);
253 }
254
255 ~TestAImpl() override {
256 test_context_->IncrementNumADeletes();
257 if (base::MessageLoop::current()->is_running())
258 Quit();
259 }
260
261 private:
262 void CallB() override {
263 b_->B(base::Bind(&TestAImpl::Quit, base::Unretained(this)));
264 }
265
266 void CallCFromB() override {
267 b_->CallC(base::Bind(&TestAImpl::Quit, base::Unretained(this)));
268 }
269
270 void Quit() {
271 base::MessageLoop::current()->QuitWhenIdle();
272 test_context_->set_a_called_quit();
273 test_context_->QuitSoon();
274 }
275
276 scoped_ptr<Connection> connection_;
277 TesterContext* test_context_;
278 TestBPtr b_;
279 StrongBinding<TestA> binding_;
280 };
281
282 class TestBImpl : public TestB {
283 public:
284 TestBImpl(Connection* connection,
285 TesterContext* test_context,
286 InterfaceRequest<TestB> request)
287 : test_context_(test_context), binding_(this, std::move(request)) {
288 connection->GetInterface(&c_);
289 }
290
291 ~TestBImpl() override {
292 test_context_->IncrementNumBDeletes();
293 if (base::MessageLoop::current()->is_running())
294 base::MessageLoop::current()->QuitWhenIdle();
295 test_context_->QuitSoon();
296 }
297
298 private:
299 void B(const Callback<void()>& callback) override {
300 test_context_->IncrementNumBCalls();
301 callback.Run();
302 }
303
304 void CallC(const Callback<void()>& callback) override {
305 test_context_->IncrementNumBCalls();
306 c_->C(callback);
307 }
308
309 TesterContext* test_context_;
310 TestCPtr c_;
311 StrongBinding<TestB> binding_;
312 };
313
314 class TestCImpl : public TestC {
315 public:
316 TestCImpl(Connection* connection,
317 TesterContext* test_context,
318 InterfaceRequest<TestC> request)
319 : test_context_(test_context), binding_(this, std::move(request)) {}
320
321 ~TestCImpl() override { test_context_->IncrementNumCDeletes(); }
322
323 private:
324 void C(const Callback<void()>& callback) override {
325 test_context_->IncrementNumCCalls();
326 callback.Run();
327 }
328
329 TesterContext* test_context_;
330 StrongBinding<TestC> binding_;
331 };
332
333 class Tester : public ShellClient,
334 public ApplicationLoader,
335 public InterfaceFactory<TestA>,
336 public InterfaceFactory<TestB>,
337 public InterfaceFactory<TestC> {
338 public:
339 Tester(TesterContext* context, const std::string& requestor_url)
340 : context_(context), requestor_url_(requestor_url) {}
341 ~Tester() override {}
342
343 private:
344 void Load(const GURL& url,
345 InterfaceRequest<mojom::ShellClient> request) override {
346 app_.reset(new ShellConnection(this, std::move(request)));
347 }
348
349 bool AcceptConnection(Connection* connection) override {
350 if (!requestor_url_.empty() &&
351 requestor_url_ != connection->GetRemoteApplicationURL()) {
352 context_->set_tester_called_quit();
353 context_->QuitSoon();
354 base::MessageLoop::current()->QuitWhenIdle();
355 return false;
356 }
357 // If we're coming from A, then add B, otherwise A.
358 if (connection->GetRemoteApplicationURL() == kTestAURLString)
359 connection->AddInterface<TestB>(this);
360 else
361 connection->AddInterface<TestA>(this);
362 return true;
363 }
364
365 void Create(Connection* connection,
366 InterfaceRequest<TestA> request) override {
367 a_bindings_.push_back(
368 new TestAImpl(app_.get(), context_, std::move(request), this));
369 }
370
371 void Create(Connection* connection,
372 InterfaceRequest<TestB> request) override {
373 new TestBImpl(connection, context_, std::move(request));
374 }
375
376 void Create(Connection* connection,
377 InterfaceRequest<TestC> request) override {
378 new TestCImpl(connection, context_, std::move(request));
379 }
380
381 TesterContext* context_;
382 scoped_ptr<ShellConnection> app_;
383 std::string requestor_url_;
384 ScopedVector<TestAImpl> a_bindings_;
385 };
386
387 class ApplicationManagerTest : public testing::Test {
388 public:
389 ApplicationManagerTest() : tester_context_(&loop_) {}
390
391 ~ApplicationManagerTest() override {}
392
393 void SetUp() override {
394 application_manager_.reset(new ApplicationManager(true));
395 test_loader_ = new TestApplicationLoader;
396 test_loader_->set_context(&context_);
397 application_manager_->set_default_loader(
398 scoped_ptr<ApplicationLoader>(test_loader_));
399
400 TestServicePtr service_proxy;
401 ConnectToInterface(application_manager_.get(), CreateShellIdentity(),
402 GURL(kTestURLString), &service_proxy);
403 test_client_.reset(new TestClient(std::move(service_proxy)));
404 }
405
406 void TearDown() override {
407 test_client_.reset();
408 application_manager_.reset();
409 }
410
411 void AddLoaderForURL(const GURL& url, const std::string& requestor_url) {
412 application_manager_->SetLoaderForURL(
413 make_scoped_ptr(new Tester(&tester_context_, requestor_url)), url);
414 }
415
416 bool HasRunningInstanceForURL(const GURL& url) {
417 ApplicationManager::TestAPI manager_test_api(application_manager_.get());
418 return manager_test_api.HasRunningInstanceForURL(url);
419 }
420
421 protected:
422 base::ShadowingAtExitManager at_exit_;
423 TestApplicationLoader* test_loader_;
424 TesterContext tester_context_;
425 TestContext context_;
426 base::MessageLoop loop_;
427 scoped_ptr<TestClient> test_client_;
428 scoped_ptr<ApplicationManager> application_manager_;
429 DISALLOW_COPY_AND_ASSIGN(ApplicationManagerTest);
430 };
431
432 TEST_F(ApplicationManagerTest, Basic) {
433 test_client_->Test("test");
434 loop_.Run();
435 EXPECT_EQ(std::string("test"), context_.last_test_string);
436 }
437
438 TEST_F(ApplicationManagerTest, ClientError) {
439 test_client_->Test("test");
440 EXPECT_TRUE(HasRunningInstanceForURL(GURL(kTestURLString)));
441 loop_.Run();
442 EXPECT_EQ(1, context_.num_impls);
443 test_client_.reset();
444 loop_.Run();
445 EXPECT_EQ(0, context_.num_impls);
446 EXPECT_TRUE(HasRunningInstanceForURL(GURL(kTestURLString)));
447 }
448
449 TEST_F(ApplicationManagerTest, Deletes) {
450 {
451 ApplicationManager am(true);
452 TestApplicationLoader* default_loader = new TestApplicationLoader;
453 default_loader->set_context(&context_);
454 TestApplicationLoader* url_loader1 = new TestApplicationLoader;
455 TestApplicationLoader* url_loader2 = new TestApplicationLoader;
456 url_loader1->set_context(&context_);
457 url_loader2->set_context(&context_);
458 am.set_default_loader(scoped_ptr<ApplicationLoader>(default_loader));
459 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader1),
460 GURL("test:test1"));
461 am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader2),
462 GURL("test:test1"));
463 }
464 EXPECT_EQ(3, context_.num_loader_deletes);
465 }
466
467 // Test for SetLoaderForURL() & set_default_loader().
468 TEST_F(ApplicationManagerTest, SetLoaders) {
469 TestApplicationLoader* default_loader = new TestApplicationLoader;
470 TestApplicationLoader* url_loader = new TestApplicationLoader;
471 application_manager_->set_default_loader(
472 scoped_ptr<ApplicationLoader>(default_loader));
473 application_manager_->SetLoaderForURL(
474 scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1"));
475
476 // test::test1 should go to url_loader.
477 TestServicePtr test_service;
478 ConnectToInterface(application_manager_.get(), CreateShellIdentity(),
479 GURL("test:test1"), &test_service);
480 EXPECT_EQ(1, url_loader->num_loads());
481 EXPECT_EQ(0, default_loader->num_loads());
482
483 // http::test1 should go to default loader.
484 ConnectToInterface(application_manager_.get(), CreateShellIdentity(),
485 GURL("http:test1"), &test_service);
486 EXPECT_EQ(1, url_loader->num_loads());
487 EXPECT_EQ(1, default_loader->num_loads());
488 }
489
490 // Confirm that the url of a service is correctly passed to another service that
491 // it loads.
492 TEST_F(ApplicationManagerTest, ACallB) {
493 // Any url can load a.
494 AddLoaderForURL(GURL(kTestAURLString), std::string());
495
496 // Only a can load b.
497 AddLoaderForURL(GURL(kTestBURLString), kTestAURLString);
498
499 TestAPtr a;
500 ConnectToInterface(application_manager_.get(), CreateShellIdentity(),
501 GURL(kTestAURLString), &a);
502 a->CallB();
503 loop_.Run();
504 EXPECT_EQ(1, tester_context_.num_b_calls());
505 EXPECT_TRUE(tester_context_.a_called_quit());
506 }
507
508 // A calls B which calls C.
509 TEST_F(ApplicationManagerTest, BCallC) {
510 // Any url can load a.
511 AddLoaderForURL(GURL(kTestAURLString), std::string());
512
513 // Only a can load b.
514 AddLoaderForURL(GURL(kTestBURLString), kTestAURLString);
515
516 TestAPtr a;
517 ConnectToInterface(application_manager_.get(), CreateShellIdentity(),
518 GURL(kTestAURLString), &a);
519 a->CallCFromB();
520 loop_.Run();
521
522 EXPECT_EQ(1, tester_context_.num_b_calls());
523 EXPECT_EQ(1, tester_context_.num_c_calls());
524 EXPECT_TRUE(tester_context_.a_called_quit());
525 }
526
527 // Confirm that a service impl will be deleted if the app that connected to
528 // it goes away.
529 TEST_F(ApplicationManagerTest, BDeleted) {
530 AddLoaderForURL(GURL(kTestAURLString), std::string());
531 AddLoaderForURL(GURL(kTestBURLString), std::string());
532
533 TestAPtr a;
534 ConnectToInterface(application_manager_.get(), CreateShellIdentity(),
535 GURL(kTestAURLString), &a);
536
537 a->CallB();
538 loop_.Run();
539
540 // Kills the a app.
541 application_manager_->SetLoaderForURL(scoped_ptr<ApplicationLoader>(),
542 GURL(kTestAURLString));
543 loop_.Run();
544
545 EXPECT_EQ(1, tester_context_.num_b_deletes());
546 }
547
548 // Confirm that the url of a service is correctly passed to another service that
549 // it loads, and that it can be rejected.
550 TEST_F(ApplicationManagerTest, ANoLoadB) {
551 // Any url can load a.
552 AddLoaderForURL(GURL(kTestAURLString), std::string());
553
554 // Only c can load b, so this will fail.
555 AddLoaderForURL(GURL(kTestBURLString), "test:TestC");
556
557 TestAPtr a;
558 ConnectToInterface(application_manager_.get(), CreateShellIdentity(),
559 GURL(kTestAURLString), &a);
560 a->CallB();
561 loop_.Run();
562 EXPECT_EQ(0, tester_context_.num_b_calls());
563
564 EXPECT_FALSE(tester_context_.a_called_quit());
565 EXPECT_TRUE(tester_context_.tester_called_quit());
566 }
567
568 TEST_F(ApplicationManagerTest, NoServiceNoLoad) {
569 AddLoaderForURL(GURL(kTestAURLString), std::string());
570
571 // There is no TestC service implementation registered with
572 // ApplicationManager, so this cannot succeed (but also shouldn't crash).
573 TestCPtr c;
574 ConnectToInterface(application_manager_.get(), CreateShellIdentity(),
575 GURL(kTestAURLString), &c);
576 c.set_connection_error_handler(
577 []() { base::MessageLoop::current()->QuitWhenIdle(); });
578
579 loop_.Run();
580 EXPECT_TRUE(c.encountered_error());
581 }
582
583 TEST_F(ApplicationManagerTest, TestEndApplicationClosure) {
584 ClosingApplicationLoader* loader = new ClosingApplicationLoader();
585 application_manager_->SetLoaderForURL(
586 scoped_ptr<ApplicationLoader>(loader), GURL("test:test"));
587
588 bool called = false;
589 scoped_ptr<ConnectToApplicationParams> params(new ConnectToApplicationParams);
590 params->SetTargetURL(GURL("test:test"));
591 params->set_on_application_end(
592 base::Bind(&QuitClosure, base::Unretained(&called)));
593 application_manager_->ConnectToApplication(std::move(params));
594 loop_.Run();
595 EXPECT_TRUE(called);
596 }
597
598 TEST_F(ApplicationManagerTest, SameIdentityShouldNotCauseDuplicateLoad) {
599 // 1 because ApplicationManagerTest connects once at startup.
600 EXPECT_EQ(1, test_loader_->num_loads());
601
602 TestServicePtr test_service;
603 ConnectToInterface(application_manager_.get(), CreateShellIdentity(),
604 GURL("mojo:foo"), &test_service);
605 EXPECT_EQ(2, test_loader_->num_loads());
606
607 // Exactly the same URL as above.
608 ConnectToInterface(application_manager_.get(), CreateShellIdentity(),
609 GURL("mojo:foo"), &test_service);
610 EXPECT_EQ(2, test_loader_->num_loads());
611
612 // A different identity because the domain is different.
613 ConnectToInterface(application_manager_.get(), CreateShellIdentity(),
614 GURL("mojo:bar"), &test_service);
615 EXPECT_EQ(3, test_loader_->num_loads());
616 }
617
618 } // namespace test
619 } // namespace shell
620 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/shell/application_manager_apptests.mojom ('k') | mojo/shell/capability_filter_test.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698