Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / mojo / application_manager / application_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/at_exit.h"
6 #include "base/bind.h"
7 #include "base/message_loop/message_loop.h"
8 #include "mojo/application_manager/application_loader.h"
9 #include "mojo/application_manager/application_manager.h"
10 #include "mojo/application_manager/background_shell_application_loader.h"
11 #include "mojo/application_manager/test.mojom.h"
12 #include "mojo/public/cpp/application/application_connection.h"
13 #include "mojo/public/cpp/application/application_delegate.h"
14 #include "mojo/public/cpp/application/application_impl.h"
15 #include "mojo/public/cpp/application/interface_factory.h"
16 #include "mojo/public/interfaces/application/service_provider.mojom.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace mojo {
20 namespace {
21
22 const char kTestURLString[] = "test:testService";
23 const char kTestAURLString[] = "test:TestA";
24 const char kTestBURLString[] = "test:TestB";
25
26 struct TestContext {
27   TestContext() : num_impls(0), num_loader_deletes(0) {}
28   std::string last_test_string;
29   int num_impls;
30   int num_loader_deletes;
31 };
32
33 class QuitMessageLoopErrorHandler : public ErrorHandler {
34  public:
35   QuitMessageLoopErrorHandler() {}
36   virtual ~QuitMessageLoopErrorHandler() {}
37
38   // |ErrorHandler| implementation:
39   virtual void OnConnectionError() OVERRIDE {
40     base::MessageLoop::current()->QuitWhenIdle();
41   }
42
43  private:
44   DISALLOW_COPY_AND_ASSIGN(QuitMessageLoopErrorHandler);
45 };
46
47 class TestServiceImpl : public InterfaceImpl<TestService> {
48  public:
49   explicit TestServiceImpl(TestContext* context) : context_(context) {
50     ++context_->num_impls;
51   }
52
53   virtual ~TestServiceImpl() { --context_->num_impls; }
54
55   virtual void OnConnectionError() OVERRIDE {
56     if (!base::MessageLoop::current()->is_running())
57       return;
58     base::MessageLoop::current()->Quit();
59   }
60
61   // TestService implementation:
62   virtual void Test(const String& test_string) OVERRIDE {
63     context_->last_test_string = test_string;
64     client()->AckTest();
65   }
66
67  private:
68   TestContext* context_;
69 };
70
71 class TestClientImpl : public TestClient {
72  public:
73   explicit TestClientImpl(TestServicePtr service)
74       : service_(service.Pass()), quit_after_ack_(false) {
75     service_.set_client(this);
76   }
77
78   virtual ~TestClientImpl() { service_.reset(); }
79
80   virtual void AckTest() OVERRIDE {
81     if (quit_after_ack_)
82       base::MessageLoop::current()->Quit();
83   }
84
85   void Test(std::string test_string) {
86     quit_after_ack_ = true;
87     service_->Test(test_string);
88   }
89
90  private:
91   TestServicePtr service_;
92   bool quit_after_ack_;
93   DISALLOW_COPY_AND_ASSIGN(TestClientImpl);
94 };
95
96 class TestApplicationLoader : public ApplicationLoader,
97                               public ApplicationDelegate,
98                               public InterfaceFactory<TestService> {
99  public:
100   TestApplicationLoader() : context_(NULL), num_loads_(0) {}
101
102   virtual ~TestApplicationLoader() {
103     if (context_)
104       ++context_->num_loader_deletes;
105     test_app_.reset(NULL);
106   }
107
108   void set_context(TestContext* context) { context_ = context; }
109   int num_loads() const { return num_loads_; }
110   std::vector<std::string> GetArgs() {
111     return test_app_->args().To<std::vector<std::string> >();
112   }
113
114  private:
115   // ApplicationLoader implementation.
116   virtual void Load(ApplicationManager* manager,
117                     const GURL& url,
118                     scoped_refptr<LoadCallbacks> callbacks) OVERRIDE {
119     ++num_loads_;
120     test_app_.reset(
121         new ApplicationImpl(this, callbacks->RegisterApplication().Pass()));
122   }
123
124   virtual void OnApplicationError(ApplicationManager* manager,
125                                   const GURL& url) OVERRIDE {}
126
127   // ApplicationDelegate implementation.
128   virtual bool ConfigureIncomingConnection(
129       ApplicationConnection* connection) OVERRIDE {
130     connection->AddService(this);
131     return true;
132   }
133
134   // InterfaceFactory implementation.
135   virtual void Create(ApplicationConnection* connection,
136                       InterfaceRequest<TestService> request) OVERRIDE {
137     BindToRequest(new TestServiceImpl(context_), &request);
138   }
139
140   scoped_ptr<ApplicationImpl> test_app_;
141   TestContext* context_;
142   int num_loads_;
143   DISALLOW_COPY_AND_ASSIGN(TestApplicationLoader);
144 };
145
146 class TesterContext {
147  public:
148   explicit TesterContext(base::MessageLoop* loop)
149       : num_b_calls_(0),
150         num_c_calls_(0),
151         num_a_deletes_(0),
152         num_b_deletes_(0),
153         num_c_deletes_(0),
154         tester_called_quit_(false),
155         a_called_quit_(false),
156         loop_(loop) {}
157
158   void IncrementNumBCalls() {
159     base::AutoLock lock(lock_);
160     num_b_calls_++;
161   }
162
163   void IncrementNumCCalls() {
164     base::AutoLock lock(lock_);
165     num_c_calls_++;
166   }
167
168   void IncrementNumADeletes() {
169     base::AutoLock lock(lock_);
170     num_a_deletes_++;
171   }
172
173   void IncrementNumBDeletes() {
174     base::AutoLock lock(lock_);
175     num_b_deletes_++;
176   }
177
178   void IncrementNumCDeletes() {
179     base::AutoLock lock(lock_);
180     num_c_deletes_++;
181   }
182
183   void set_tester_called_quit() {
184     base::AutoLock lock(lock_);
185     tester_called_quit_ = true;
186   }
187
188   void set_a_called_quit() {
189     base::AutoLock lock(lock_);
190     a_called_quit_ = true;
191   }
192
193   int num_b_calls() {
194     base::AutoLock lock(lock_);
195     return num_b_calls_;
196   }
197   int num_c_calls() {
198     base::AutoLock lock(lock_);
199     return num_c_calls_;
200   }
201   int num_a_deletes() {
202     base::AutoLock lock(lock_);
203     return num_a_deletes_;
204   }
205   int num_b_deletes() {
206     base::AutoLock lock(lock_);
207     return num_b_deletes_;
208   }
209   int num_c_deletes() {
210     base::AutoLock lock(lock_);
211     return num_c_deletes_;
212   }
213   bool tester_called_quit() {
214     base::AutoLock lock(lock_);
215     return tester_called_quit_;
216   }
217   bool a_called_quit() {
218     base::AutoLock lock(lock_);
219     return a_called_quit_;
220   }
221
222   void QuitSoon() {
223     loop_->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
224   }
225
226  private:
227   // lock_ protects all members except for loop_ which must be unchanged for the
228   // lifetime of this class.
229   base::Lock lock_;
230   int num_b_calls_;
231   int num_c_calls_;
232   int num_a_deletes_;
233   int num_b_deletes_;
234   int num_c_deletes_;
235   bool tester_called_quit_;
236   bool a_called_quit_;
237
238   base::MessageLoop* loop_;
239 };
240
241 // Used to test that the requestor url will be correctly passed.
242 class TestAImpl : public InterfaceImpl<TestA> {
243  public:
244   TestAImpl(ApplicationConnection* connection, TesterContext* test_context)
245       : test_context_(test_context) {
246     connection->ConnectToApplication(kTestBURLString)->ConnectToService(&b_);
247   }
248   virtual ~TestAImpl() {
249     test_context_->IncrementNumADeletes();
250     if (base::MessageLoop::current()->is_running())
251       Quit();
252   }
253
254  private:
255   virtual void CallB() OVERRIDE {
256     b_->B(base::Bind(&TestAImpl::Quit, base::Unretained(this)));
257   }
258
259   virtual void CallCFromB() OVERRIDE {
260     b_->CallC(base::Bind(&TestAImpl::Quit, base::Unretained(this)));
261   }
262
263   void Quit() {
264     base::MessageLoop::current()->Quit();
265     test_context_->set_a_called_quit();
266     test_context_->QuitSoon();
267   }
268
269   TesterContext* test_context_;
270   TestBPtr b_;
271 };
272
273 class TestBImpl : public InterfaceImpl<TestB> {
274  public:
275   TestBImpl(ApplicationConnection* connection, TesterContext* test_context)
276       : test_context_(test_context) {
277     connection->ConnectToService(&c_);
278   }
279
280   virtual ~TestBImpl() {
281     test_context_->IncrementNumBDeletes();
282     if (base::MessageLoop::current()->is_running())
283       base::MessageLoop::current()->Quit();
284     test_context_->QuitSoon();
285   }
286
287  private:
288   virtual void B(const mojo::Callback<void()>& callback) OVERRIDE {
289     test_context_->IncrementNumBCalls();
290     callback.Run();
291   }
292
293   virtual void CallC(const mojo::Callback<void()>& callback) OVERRIDE {
294     test_context_->IncrementNumBCalls();
295     c_->C(callback);
296   }
297
298   TesterContext* test_context_;
299   TestCPtr c_;
300 };
301
302 class TestCImpl : public InterfaceImpl<TestC> {
303  public:
304   TestCImpl(ApplicationConnection* connection, TesterContext* test_context)
305       : test_context_(test_context) {}
306
307   virtual ~TestCImpl() { test_context_->IncrementNumCDeletes(); }
308
309  private:
310   virtual void C(const mojo::Callback<void()>& callback) OVERRIDE {
311     test_context_->IncrementNumCCalls();
312     callback.Run();
313   }
314   TesterContext* test_context_;
315 };
316
317 class Tester : public ApplicationDelegate,
318                public ApplicationLoader,
319                public InterfaceFactory<TestA>,
320                public InterfaceFactory<TestB>,
321                public InterfaceFactory<TestC> {
322  public:
323   Tester(TesterContext* context, const std::string& requestor_url)
324       : context_(context), requestor_url_(requestor_url) {}
325   virtual ~Tester() {}
326
327  private:
328   virtual void Load(ApplicationManager* manager,
329                     const GURL& url,
330                     scoped_refptr<LoadCallbacks> callbacks) OVERRIDE {
331     app_.reset(
332         new ApplicationImpl(this, callbacks->RegisterApplication().Pass()));
333   }
334
335   virtual void OnApplicationError(ApplicationManager* manager,
336                                   const GURL& url) OVERRIDE {}
337
338   virtual bool ConfigureIncomingConnection(
339       ApplicationConnection* connection) OVERRIDE {
340     if (!requestor_url_.empty() &&
341         requestor_url_ != connection->GetRemoteApplicationURL()) {
342       context_->set_tester_called_quit();
343       context_->QuitSoon();
344       base::MessageLoop::current()->Quit();
345       return false;
346     }
347     // If we're coming from A, then add B, otherwise A.
348     if (connection->GetRemoteApplicationURL() == kTestAURLString)
349       connection->AddService<TestB>(this);
350     else
351       connection->AddService<TestA>(this);
352     return true;
353   }
354
355   virtual bool ConfigureOutgoingConnection(
356       ApplicationConnection* connection) OVERRIDE {
357     // If we're connecting to B, then add C.
358     if (connection->GetRemoteApplicationURL() == kTestBURLString)
359       connection->AddService<TestC>(this);
360     return true;
361   }
362
363   virtual void Create(ApplicationConnection* connection,
364                       InterfaceRequest<TestA> request) OVERRIDE {
365     BindToRequest(new TestAImpl(connection, context_), &request);
366   }
367
368   virtual void Create(ApplicationConnection* connection,
369                       InterfaceRequest<TestB> request) OVERRIDE {
370     BindToRequest(new TestBImpl(connection, context_), &request);
371   }
372
373   virtual void Create(ApplicationConnection* connection,
374                       InterfaceRequest<TestC> request) OVERRIDE {
375     BindToRequest(new TestCImpl(connection, context_), &request);
376   }
377
378   TesterContext* context_;
379   scoped_ptr<ApplicationImpl> app_;
380   std::string requestor_url_;
381 };
382
383 class TestServiceInterceptor : public ApplicationManager::Interceptor {
384  public:
385   TestServiceInterceptor() : call_count_(0) {}
386
387   virtual ServiceProviderPtr OnConnectToClient(
388       const GURL& url,
389       ServiceProviderPtr service_provider) OVERRIDE {
390     ++call_count_;
391     url_ = url;
392     return service_provider.Pass();
393   }
394
395   std::string url_spec() const {
396     if (!url_.is_valid())
397       return "invalid url";
398     return url_.spec();
399   }
400
401   int call_count() const { return call_count_; }
402
403  private:
404   int call_count_;
405   GURL url_;
406   DISALLOW_COPY_AND_ASSIGN(TestServiceInterceptor);
407 };
408
409 }  // namespace
410
411 class ApplicationManagerTest : public testing::Test {
412  public:
413   ApplicationManagerTest() : tester_context_(&loop_) {}
414
415   virtual ~ApplicationManagerTest() {}
416
417   virtual void SetUp() OVERRIDE {
418     application_manager_.reset(new ApplicationManager);
419     TestApplicationLoader* default_loader = new TestApplicationLoader;
420     default_loader->set_context(&context_);
421     application_manager_->set_default_loader(
422         scoped_ptr<ApplicationLoader>(default_loader));
423
424     TestServicePtr service_proxy;
425     application_manager_->ConnectToService(GURL(kTestURLString),
426                                            &service_proxy);
427     test_client_.reset(new TestClientImpl(service_proxy.Pass()));
428   }
429
430   virtual void TearDown() OVERRIDE {
431     test_client_.reset(NULL);
432     application_manager_.reset(NULL);
433   }
434
435   scoped_ptr<BackgroundShellApplicationLoader> MakeLoader(
436       const std::string& requestor_url) {
437     scoped_ptr<ApplicationLoader> real_loader(
438         new Tester(&tester_context_, requestor_url));
439     scoped_ptr<BackgroundShellApplicationLoader> loader(
440         new BackgroundShellApplicationLoader(real_loader.Pass(),
441                                              std::string(),
442                                              base::MessageLoop::TYPE_DEFAULT));
443     return loader.Pass();
444   }
445
446   void AddLoaderForURL(const GURL& url, const std::string& requestor_url) {
447     application_manager_->SetLoaderForURL(
448         MakeLoader(requestor_url).PassAs<ApplicationLoader>(), url);
449   }
450
451   bool HasFactoryForTestURL() {
452     ApplicationManager::TestAPI manager_test_api(application_manager_.get());
453     return manager_test_api.HasFactoryForURL(GURL(kTestURLString));
454   }
455
456  protected:
457   base::ShadowingAtExitManager at_exit_;
458   TesterContext tester_context_;
459   TestContext context_;
460   base::MessageLoop loop_;
461   scoped_ptr<TestClientImpl> test_client_;
462   scoped_ptr<ApplicationManager> application_manager_;
463   DISALLOW_COPY_AND_ASSIGN(ApplicationManagerTest);
464 };
465
466 TEST_F(ApplicationManagerTest, Basic) {
467   test_client_->Test("test");
468   loop_.Run();
469   EXPECT_EQ(std::string("test"), context_.last_test_string);
470 }
471
472 // Confirm that no arguments are sent to an application by default.
473 TEST_F(ApplicationManagerTest, NoArgs) {
474   ApplicationManager am;
475   GURL test_url("test:test");
476   TestContext context;
477   TestApplicationLoader* loader = new TestApplicationLoader;
478   loader->set_context(&context);
479   am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url);
480   TestServicePtr test_service;
481   am.ConnectToService(test_url, &test_service);
482   TestClientImpl test_client(test_service.Pass());
483   test_client.Test("test");
484   loop_.Run();
485   std::vector<std::string> app_args = loader->GetArgs();
486   EXPECT_EQ(0U, app_args.size());
487 }
488
489 // Confirm that arguments are sent to an application.
490 TEST_F(ApplicationManagerTest, Args) {
491   ApplicationManager am;
492   GURL test_url("test:test");
493   std::vector<std::string> args;
494   args.push_back("test_arg1");
495   args.push_back("test_arg2");
496   am.SetArgsForURL(args, test_url);
497   TestContext context;
498   TestApplicationLoader* loader = new TestApplicationLoader;
499   loader->set_context(&context);
500   am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url);
501   TestServicePtr test_service;
502   am.ConnectToService(test_url, &test_service);
503   TestClientImpl test_client(test_service.Pass());
504   test_client.Test("test");
505   loop_.Run();
506   std::vector<std::string> app_args = loader->GetArgs();
507   ASSERT_EQ(args.size(), app_args.size());
508   EXPECT_EQ(args[0], app_args[0]);
509   EXPECT_EQ(args[1], app_args[1]);
510 }
511
512 TEST_F(ApplicationManagerTest, ClientError) {
513   test_client_->Test("test");
514   EXPECT_TRUE(HasFactoryForTestURL());
515   loop_.Run();
516   EXPECT_EQ(1, context_.num_impls);
517   test_client_.reset(NULL);
518   loop_.Run();
519   EXPECT_EQ(0, context_.num_impls);
520   EXPECT_TRUE(HasFactoryForTestURL());
521 }
522
523 TEST_F(ApplicationManagerTest, Deletes) {
524   {
525     ApplicationManager am;
526     TestApplicationLoader* default_loader = new TestApplicationLoader;
527     default_loader->set_context(&context_);
528     TestApplicationLoader* url_loader1 = new TestApplicationLoader;
529     TestApplicationLoader* url_loader2 = new TestApplicationLoader;
530     url_loader1->set_context(&context_);
531     url_loader2->set_context(&context_);
532     TestApplicationLoader* scheme_loader1 = new TestApplicationLoader;
533     TestApplicationLoader* scheme_loader2 = new TestApplicationLoader;
534     scheme_loader1->set_context(&context_);
535     scheme_loader2->set_context(&context_);
536     am.set_default_loader(scoped_ptr<ApplicationLoader>(default_loader));
537     am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader1),
538                        GURL("test:test1"));
539     am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader2),
540                        GURL("test:test1"));
541     am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader1),
542                           "test");
543     am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader2),
544                           "test");
545   }
546   EXPECT_EQ(5, context_.num_loader_deletes);
547 }
548
549 // Confirm that both urls and schemes can have their loaders explicitly set.
550 TEST_F(ApplicationManagerTest, SetLoaders) {
551   TestApplicationLoader* default_loader = new TestApplicationLoader;
552   TestApplicationLoader* url_loader = new TestApplicationLoader;
553   TestApplicationLoader* scheme_loader = new TestApplicationLoader;
554   application_manager_->set_default_loader(
555       scoped_ptr<ApplicationLoader>(default_loader));
556   application_manager_->SetLoaderForURL(
557       scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1"));
558   application_manager_->SetLoaderForScheme(
559       scoped_ptr<ApplicationLoader>(scheme_loader), "test");
560
561   // test::test1 should go to url_loader.
562   TestServicePtr test_service;
563   application_manager_->ConnectToService(GURL("test:test1"), &test_service);
564   EXPECT_EQ(1, url_loader->num_loads());
565   EXPECT_EQ(0, scheme_loader->num_loads());
566   EXPECT_EQ(0, default_loader->num_loads());
567
568   // test::test2 should go to scheme loader.
569   application_manager_->ConnectToService(GURL("test:test2"), &test_service);
570   EXPECT_EQ(1, url_loader->num_loads());
571   EXPECT_EQ(1, scheme_loader->num_loads());
572   EXPECT_EQ(0, default_loader->num_loads());
573
574   // http::test1 should go to default loader.
575   application_manager_->ConnectToService(GURL("http:test1"), &test_service);
576   EXPECT_EQ(1, url_loader->num_loads());
577   EXPECT_EQ(1, scheme_loader->num_loads());
578   EXPECT_EQ(1, default_loader->num_loads());
579 }
580
581 // Confirm that the url of a service is correctly passed to another service that
582 // it loads.
583 TEST_F(ApplicationManagerTest, ACallB) {
584   // Any url can load a.
585   AddLoaderForURL(GURL(kTestAURLString), std::string());
586
587   // Only a can load b.
588   AddLoaderForURL(GURL(kTestBURLString), kTestAURLString);
589
590   TestAPtr a;
591   application_manager_->ConnectToService(GURL(kTestAURLString), &a);
592   a->CallB();
593   loop_.Run();
594   EXPECT_EQ(1, tester_context_.num_b_calls());
595   EXPECT_TRUE(tester_context_.a_called_quit());
596 }
597
598 // A calls B which calls C.
599 TEST_F(ApplicationManagerTest, BCallC) {
600   // Any url can load a.
601   AddLoaderForURL(GURL(kTestAURLString), std::string());
602
603   // Only a can load b.
604   AddLoaderForURL(GURL(kTestBURLString), kTestAURLString);
605
606   TestAPtr a;
607   application_manager_->ConnectToService(GURL(kTestAURLString), &a);
608   a->CallCFromB();
609   loop_.Run();
610
611   EXPECT_EQ(1, tester_context_.num_b_calls());
612   EXPECT_EQ(1, tester_context_.num_c_calls());
613   EXPECT_TRUE(tester_context_.a_called_quit());
614 }
615
616 // Confirm that a service impl will be deleted if the app that connected to
617 // it goes away.
618 TEST_F(ApplicationManagerTest, BDeleted) {
619   AddLoaderForURL(GURL(kTestAURLString), std::string());
620   AddLoaderForURL(GURL(kTestBURLString), std::string());
621
622   TestAPtr a;
623   application_manager_->ConnectToService(GURL(kTestAURLString), &a);
624
625   a->CallB();
626   loop_.Run();
627
628   // Kills the a app.
629   application_manager_->SetLoaderForURL(scoped_ptr<ApplicationLoader>(),
630                                         GURL(kTestAURLString));
631   loop_.Run();
632
633   EXPECT_EQ(1, tester_context_.num_b_deletes());
634 }
635
636 // Confirm that the url of a service is correctly passed to another service that
637 // it loads, and that it can be rejected.
638 TEST_F(ApplicationManagerTest, ANoLoadB) {
639   // Any url can load a.
640   AddLoaderForURL(GURL(kTestAURLString), std::string());
641
642   // Only c can load b, so this will fail.
643   AddLoaderForURL(GURL(kTestBURLString), "test:TestC");
644
645   TestAPtr a;
646   application_manager_->ConnectToService(GURL(kTestAURLString), &a);
647   a->CallB();
648   loop_.Run();
649   EXPECT_EQ(0, tester_context_.num_b_calls());
650
651   EXPECT_FALSE(tester_context_.a_called_quit());
652   EXPECT_TRUE(tester_context_.tester_called_quit());
653 }
654
655 TEST_F(ApplicationManagerTest, NoServiceNoLoad) {
656   AddLoaderForURL(GURL(kTestAURLString), std::string());
657
658   // There is no TestC service implementation registered with
659   // ApplicationManager, so this cannot succeed (but also shouldn't crash).
660   TestCPtr c;
661   application_manager_->ConnectToService(GURL(kTestAURLString), &c);
662   QuitMessageLoopErrorHandler quitter;
663   c.set_error_handler(&quitter);
664
665   loop_.Run();
666   EXPECT_TRUE(c.encountered_error());
667 }
668
669 TEST_F(ApplicationManagerTest, Interceptor) {
670   TestServiceInterceptor interceptor;
671   TestApplicationLoader* default_loader = new TestApplicationLoader;
672   application_manager_->set_default_loader(
673       scoped_ptr<ApplicationLoader>(default_loader));
674   application_manager_->SetInterceptor(&interceptor);
675
676   std::string url("test:test3");
677   TestServicePtr test_service;
678   application_manager_->ConnectToService(GURL(url), &test_service);
679
680   EXPECT_EQ(1, interceptor.call_count());
681   EXPECT_EQ(url, interceptor.url_spec());
682   EXPECT_EQ(1, default_loader->num_loads());
683 }
684
685 }  // namespace mojo