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.
5 #include "gin/modules/module_registry.h"
8 #include "base/message_loop/message_loop.h"
9 #include "gin/modules/module_registry_observer.h"
10 #include "gin/modules/module_runner_delegate.h"
11 #include "gin/public/context_holder.h"
12 #include "gin/public/isolate_holder.h"
13 #include "gin/shell_runner.h"
14 #include "gin/test/v8_test.h"
15 #include "v8/include/v8.h"
22 TestHelper(v8::Isolate
* isolate
)
23 : delegate(std::vector
<base::FilePath
>()),
24 runner(new ShellRunner(&delegate
, isolate
)),
28 base::MessageLoop message_loop
;
29 ModuleRunnerDelegate delegate
;
30 scoped_ptr
<ShellRunner
> runner
;
34 class ModuleRegistryObserverImpl
: public ModuleRegistryObserver
{
36 ModuleRegistryObserverImpl() : did_add_count_(0) {}
38 void OnDidAddPendingModule(
39 const std::string
& id
,
40 const std::vector
<std::string
>& dependencies
) override
{
43 dependencies_
= dependencies
;
46 int did_add_count() { return did_add_count_
; }
47 const std::string
& id() const { return id_
; }
48 const std::vector
<std::string
>& dependencies() const { return dependencies_
; }
53 std::vector
<std::string
> dependencies_
;
55 DISALLOW_COPY_AND_ASSIGN(ModuleRegistryObserverImpl
);
58 void NestedCallback(v8::Handle
<v8::Value
> value
) {
59 FAIL() << "Should not be called";
62 void OnModuleLoaded(TestHelper
* helper
,
65 v8::Handle
<v8::Value
> value
) {
66 ASSERT_TRUE(value
->IsNumber());
67 v8::Handle
<v8::Integer
> int_value
= v8::Handle
<v8::Integer
>::Cast(value
);
68 *counter
+= int_value
->Value();
69 ModuleRegistry::From(helper
->runner
->GetContextHolder()->context())
70 ->LoadModule(isolate
, "two", base::Bind(NestedCallback
));
73 void OnModuleLoadedNoOp(v8::Handle
<v8::Value
> value
) {
74 ASSERT_TRUE(value
->IsNumber());
79 typedef V8Test ModuleRegistryTest
;
81 // Verifies ModuleRegistry is not available after ContextHolder has been
83 TEST_F(ModuleRegistryTest
, DestroyedWithContext
) {
84 v8::Isolate::Scope
isolate_scope(instance_
->isolate());
85 v8::HandleScope
handle_scope(instance_
->isolate());
86 v8::Handle
<v8::Context
> context
= v8::Context::New(
87 instance_
->isolate(), NULL
, v8::Handle
<v8::ObjectTemplate
>());
89 ContextHolder
context_holder(instance_
->isolate());
90 context_holder
.SetContext(context
);
91 ModuleRegistry
* registry
= ModuleRegistry::From(context
);
92 EXPECT_TRUE(registry
!= NULL
);
94 ModuleRegistry
* registry
= ModuleRegistry::From(context
);
95 EXPECT_TRUE(registry
== NULL
);
98 // Verifies ModuleRegistryObserver is notified appropriately.
99 TEST_F(ModuleRegistryTest
, ModuleRegistryObserverTest
) {
100 TestHelper
helper(instance_
->isolate());
102 "define('id', ['dep1', 'dep2'], function() {"
103 " return function() {};"
106 ModuleRegistryObserverImpl observer
;
107 ModuleRegistry::From(helper
.runner
->GetContextHolder()->context())->
108 AddObserver(&observer
);
109 helper
.runner
->Run(source
, "script");
110 ModuleRegistry::From(helper
.runner
->GetContextHolder()->context())->
111 RemoveObserver(&observer
);
112 EXPECT_EQ(1, observer
.did_add_count());
113 EXPECT_EQ("id", observer
.id());
114 ASSERT_EQ(2u, observer
.dependencies().size());
115 EXPECT_EQ("dep1", observer
.dependencies()[0]);
116 EXPECT_EQ("dep2", observer
.dependencies()[1]);
119 // Verifies that multiple LoadModule calls for the same module are handled
121 TEST_F(ModuleRegistryTest
, LoadModuleTest
) {
122 TestHelper
helper(instance_
->isolate());
125 "define('one', [], function() {"
129 ModuleRegistry::LoadModuleCallback callback
=
130 base::Bind(OnModuleLoaded
, &helper
, instance_
->isolate(), &counter
);
131 for (int i
= 0; i
< 3; i
++) {
132 ModuleRegistry::From(helper
.runner
->GetContextHolder()->context())
133 ->LoadModule(instance_
->isolate(), "one", callback
);
135 EXPECT_EQ(0, counter
);
136 helper
.runner
->Run(source
, "script");
137 EXPECT_EQ(3, counter
);
140 // Verifies that explicitly loading a module that's already pending does
141 // not cause the ModuleRegistry's unsatisfied_dependency set to grow.
142 TEST_F(ModuleRegistryTest
, UnsatisfiedDependenciesTest
) {
143 TestHelper
helper(instance_
->isolate());
145 "define('one', ['no_such_module'], function(nsm) {"
148 ModuleRegistry
* registry
=
149 ModuleRegistry::From(helper
.runner
->GetContextHolder()->context());
151 std::set
<std::string
> no_such_module_set
;
152 no_such_module_set
.insert("no_such_module");
154 // Adds one unsatisfied dependency on "no-such-module".
155 helper
.runner
->Run(source
, "script");
156 EXPECT_EQ(no_such_module_set
, registry
->unsatisfied_dependencies());
158 // Should have no effect on the unsatisfied_dependencies set.
159 ModuleRegistry::LoadModuleCallback callback
= base::Bind(OnModuleLoadedNoOp
);
160 registry
->LoadModule(instance_
->isolate(), "one", callback
);
161 EXPECT_EQ(no_such_module_set
, registry
->unsatisfied_dependencies());