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

Side by Side Diff: chrome/renderer/module_system_unittest.cc

Issue 9835039: Make app_custom_bindings.js lazily evaluated so it doesn't execute on every page load. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: respond to comments Created 8 years, 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/callback.h" 5 #include "base/callback.h"
6 #include "base/memory/scoped_ptr.h" 6 #include "base/memory/scoped_ptr.h"
7 #include "base/string_piece.h" 7 #include "base/string_piece.h"
8 #include "chrome/renderer/module_system.h" 8 #include "chrome/renderer/module_system.h"
9 #include "testing/gtest/include/gtest/gtest.h" 9 #include "testing/gtest/include/gtest/gtest.h"
10 10
11 #include <map> 11 #include <map>
12 #include <string> 12 #include <string>
13 13
14 // Native JS functions for doing asserts. 14 // Native JS functions for doing asserts.
15 class AssertNatives : public NativeHandler { 15 class AssertNatives : public NativeHandler {
16 public: 16 public:
17 AssertNatives() 17 AssertNatives()
18 : native_function_called_(false), 18 : assertion_made_(false),
19 failed_(false) { 19 failed_(false) {
20 RouteFunction("AssertTrue", base::Bind(&AssertNatives::AssertTrue, 20 RouteFunction("AssertTrue", base::Bind(&AssertNatives::AssertTrue,
21 base::Unretained(this))); 21 base::Unretained(this)));
22 } 22 }
23 23
24 bool native_function_called() { return native_function_called_; } 24 bool assertion_made() { return assertion_made_; }
25 bool failed() { return failed_; } 25 bool failed() { return failed_; }
26 26
27 v8::Handle<v8::Value> AssertTrue(const v8::Arguments& args) { 27 v8::Handle<v8::Value> AssertTrue(const v8::Arguments& args) {
28 native_function_called_ = true; 28 assertion_made_ = true;
29 failed_ = failed_ || !args[0]->ToBoolean()->Value(); 29 failed_ = failed_ || !args[0]->ToBoolean()->Value();
30 return v8::Undefined(); 30 return v8::Undefined();
31 } 31 }
32 32
33 private: 33 private:
34 bool native_function_called_; 34 bool assertion_made_;
35 bool failed_; 35 bool failed_;
36 }; 36 };
37 37
38 class CounterNatives : public NativeHandler {
39 public:
40 CounterNatives()
41 : counter_(0) {
not at google - send to devlin 2012/03/26 02:29:49 nit: on same line as CounterNatives()
koz (OOO until 15th September) 2012/03/26 03:58:59 Done.
42 RouteFunction("Get", base::Bind(&CounterNatives::Get,
43 base::Unretained(this)));
44 RouteFunction("Increment", base::Bind(&CounterNatives::Increment,
45 base::Unretained(this)));
46 }
47
48 v8::Handle<v8::Value> Get(const v8::Arguments& args) {
49 return v8::Integer::New(counter_);
50 }
51
52 v8::Handle<v8::Value> Increment(const v8::Arguments& args) {
53 counter_++;
54 return v8::Undefined();
55 }
56
57 private:
58 int counter_;
59 };
60
38 class StringSourceMap : public ModuleSystem::SourceMap { 61 class StringSourceMap : public ModuleSystem::SourceMap {
39 public: 62 public:
40 StringSourceMap() {} 63 StringSourceMap() {}
41 virtual ~StringSourceMap() {} 64 virtual ~StringSourceMap() {}
42 65
43 v8::Handle<v8::Value> GetSource(const std::string& name) OVERRIDE { 66 v8::Handle<v8::Value> GetSource(const std::string& name) OVERRIDE {
44 if (source_map_.count(name) == 0) 67 if (source_map_.count(name) == 0)
45 return v8::Undefined(); 68 return v8::Undefined();
46 return v8::String::New(source_map_[name].c_str()); 69 return v8::String::New(source_map_[name].c_str());
47 } 70 }
48 71
49 bool Contains(const std::string& name) OVERRIDE { 72 bool Contains(const std::string& name) OVERRIDE {
50 return source_map_.count(name); 73 return source_map_.count(name);
51 } 74 }
52 75
53 void RegisterModule(const std::string& name, const std::string& source) { 76 void RegisterModule(const std::string& name, const std::string& source) {
54 source_map_[name] = source; 77 source_map_[name] = source;
55 } 78 }
56 79
57 private: 80 private:
58 std::map<std::string, std::string> source_map_; 81 std::map<std::string, std::string> source_map_;
59 }; 82 };
60 83
61 // Native JS functions for disabling injection in ModuleSystem.
62 class DisableNativesHandler : public NativeHandler {
63 public:
64 explicit DisableNativesHandler(ModuleSystem* module_system)
65 : module_system_(module_system) {
66 RouteFunction("DisableNatives",
67 base::Bind(&DisableNativesHandler::DisableNatives,
68 base::Unretained(this)));
69 }
70
71 v8::Handle<v8::Value> DisableNatives(const v8::Arguments& args) {
72 module_system_->set_natives_enabled(false);
73 return v8::Undefined();
74 }
75
76 private:
77 ModuleSystem* module_system_;
78 };
79
80 class ModuleSystemTest : public testing::Test { 84 class ModuleSystemTest : public testing::Test {
81 public: 85 public:
82 ModuleSystemTest() 86 ModuleSystemTest()
83 : context_(v8::Context::New()), 87 : context_(v8::Context::New()),
84 source_map_(new StringSourceMap()) { 88 source_map_(new StringSourceMap()),
89 should_assertions_be_made_(true) {
85 context_->Enter(); 90 context_->Enter();
86 assert_natives_ = new AssertNatives(); 91 assert_natives_ = new AssertNatives();
87 module_system_.reset(new ModuleSystem(source_map_.get())); 92 module_system_.reset(new ModuleSystem(source_map_.get()));
88 module_system_->RegisterNativeHandler("assert", scoped_ptr<NativeHandler>( 93 module_system_->RegisterNativeHandler("assert", scoped_ptr<NativeHandler>(
89 assert_natives_)); 94 assert_natives_));
90 RegisterModule("add", "exports.Add = function(x, y) { return x + y; };"); 95 RegisterModule("add", "exports.Add = function(x, y) { return x + y; };");
91 } 96 }
92 97
93 ~ModuleSystemTest() { 98 ~ModuleSystemTest() {
94 context_->Exit(); 99 context_->Exit();
95 context_.Dispose(); 100 context_.Dispose();
96 } 101 }
97 102
98 void RegisterModule(const std::string& name, const std::string& code) { 103 void RegisterModule(const std::string& name, const std::string& code) {
99 source_map_->RegisterModule(name, code); 104 source_map_->RegisterModule(name, code);
100 } 105 }
101 106
102 virtual void TearDown() { 107 virtual void TearDown() {
103 // All tests must call a native function at least once. 108 // All tests must call a native function at least once.
104 ASSERT_TRUE(assert_natives_->native_function_called()); 109 ASSERT_FALSE(try_catch_.HasCaught());
110 ASSERT_EQ(should_assertions_be_made_,
111 assert_natives_->assertion_made());
105 ASSERT_FALSE(assert_natives_->failed()); 112 ASSERT_FALSE(assert_natives_->failed());
106 ASSERT_FALSE(try_catch_.HasCaught()); 113 }
114
115 void ExpectNoAssertionsMade() {
not at google - send to devlin 2012/03/26 02:29:49 This is an unfortunate name in the context of gtes
koz (OOO until 15th September) 2012/03/26 03:58:59 Yeah. I can't think of a better name that's not su
116 should_assertions_be_made_ = false;
117 }
118
119 v8::Handle<v8::Object> CreateGlobal(const std::string& name) {
120 v8::HandleScope handle_scope;
121 v8::Handle<v8::Object> object = v8::Object::New();
122 v8::Context::GetCurrent()->Global()->Set(v8::String::New(name.c_str()),
123 object);
124 return handle_scope.Close(object);
107 } 125 }
108 126
109 v8::Persistent<v8::Context> context_; 127 v8::Persistent<v8::Context> context_;
110 v8::HandleScope handle_scope_; 128 v8::HandleScope handle_scope_;
111 v8::TryCatch try_catch_; 129 v8::TryCatch try_catch_;
112 AssertNatives* assert_natives_; 130 AssertNatives* assert_natives_;
113 scoped_ptr<StringSourceMap> source_map_; 131 scoped_ptr<StringSourceMap> source_map_;
114 scoped_ptr<ModuleSystem> module_system_; 132 scoped_ptr<ModuleSystem> module_system_;
133 bool should_assertions_be_made_;
115 }; 134 };
116 135
117 TEST_F(ModuleSystemTest, TestRequire) { 136 TEST_F(ModuleSystemTest, TestRequire) {
137 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
118 RegisterModule("test", 138 RegisterModule("test",
119 "var Add = require('add').Add;" 139 "var Add = require('add').Add;"
120 "requireNative('assert').AssertTrue(Add(3, 5) == 8);"); 140 "requireNative('assert').AssertTrue(Add(3, 5) == 8);");
121 module_system_->Require("test"); 141 module_system_->Require("test");
122 } 142 }
123 143
124 TEST_F(ModuleSystemTest, TestNestedRequire) { 144 TEST_F(ModuleSystemTest, TestNestedRequire) {
145 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
125 RegisterModule("double", 146 RegisterModule("double",
126 "var Add = require('add').Add;" 147 "var Add = require('add').Add;"
127 "exports.Double = function(x) { return Add(x, x); };"); 148 "exports.Double = function(x) { return Add(x, x); };");
128 RegisterModule("test", 149 RegisterModule("test",
129 "var Double = require('double').Double;" 150 "var Double = require('double').Double;"
130 "requireNative('assert').AssertTrue(Double(3) == 6);"); 151 "requireNative('assert').AssertTrue(Double(3) == 6);");
131 module_system_->Require("test"); 152 module_system_->Require("test");
132 } 153 }
133 154
134 TEST_F(ModuleSystemTest, TestModuleInsulation) { 155 TEST_F(ModuleSystemTest, TestModuleInsulation) {
156 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
135 RegisterModule("x", 157 RegisterModule("x",
136 "var x = 10;" 158 "var x = 10;"
137 "exports.X = function() { return x; };"); 159 "exports.X = function() { return x; };");
138 RegisterModule("y", 160 RegisterModule("y",
139 "var x = 15;" 161 "var x = 15;"
140 "require('x');" 162 "require('x');"
141 "exports.Y = function() { return x; };"); 163 "exports.Y = function() { return x; };");
142 RegisterModule("test", 164 RegisterModule("test",
143 "var Y = require('y').Y;" 165 "var Y = require('y').Y;"
144 "var X = require('x').X;" 166 "var X = require('x').X;"
145 "var assert = requireNative('assert');" 167 "var assert = requireNative('assert');"
146 "assert.AssertTrue(!this.hasOwnProperty('x'));" 168 "assert.AssertTrue(!this.hasOwnProperty('x'));"
147 "assert.AssertTrue(Y() == 15);" 169 "assert.AssertTrue(Y() == 15);"
148 "assert.AssertTrue(X() == 10);"); 170 "assert.AssertTrue(X() == 10);");
149 module_system_->Require("test"); 171 module_system_->Require("test");
150 } 172 }
151 173
152 TEST_F(ModuleSystemTest, TestDisableNativesPreventsNativeModulesBeingLoaded) { 174 TEST_F(ModuleSystemTest, TestNativesAreDisabledOutsideANativesEnabledScope) {
153 module_system_->RegisterNativeHandler("disable",
154 scoped_ptr<NativeHandler>(
155 new DisableNativesHandler(module_system_.get())));
156 RegisterModule("test", 175 RegisterModule("test",
157 "var assert = requireNative('assert');" 176 "var assert;"
158 "var disable = requireNative('disable');"
159 "disable.DisableNatives();"
160 "var caught = false;"
161 "try {" 177 "try {"
162 " requireNative('assert');" 178 " assert = requireNative('assert');"
163 "} catch (e) {" 179 "} catch (e) {"
164 " caught = true;" 180 " caught = true;"
165 "}" 181 "}"
166 "assert.AssertTrue(caught);"); 182 "if (assert) {"
183 " assert.AssertTrue(true);"
184 "}");
167 module_system_->Require("test"); 185 module_system_->Require("test");
186 ExpectNoAssertionsMade();
187 }
188
189 TEST_F(ModuleSystemTest, TestNativesAreEnabledWithinANativesEnabledScope) {
190 RegisterModule("test",
191 "var assert = requireNative('assert');"
192 "assert.AssertTrue(true);");
193
194 {
195 ModuleSystem::NativesEnabledScope natives_enabled(module_system_.get());
196 {
197 ModuleSystem::NativesEnabledScope natives_enabled_inner(
198 module_system_.get());
199 }
200 module_system_->Require("test");
201 }
168 } 202 }
169 203
170 TEST_F(ModuleSystemTest, TestLazyField) { 204 TEST_F(ModuleSystemTest, TestLazyField) {
205 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
171 RegisterModule("lazy", 206 RegisterModule("lazy",
172 "exports.x = 5;"); 207 "exports.x = 5;");
173 208
174 v8::Handle<v8::Object> object = v8::Object::New(); 209 v8::Handle<v8::Object> object = CreateGlobal("object");
175 v8::Context::GetCurrent()->Global()->Set(v8::String::New("object"), object);
176 210
177 module_system_->SetLazyField(object, "blah", "lazy", "x"); 211 module_system_->SetLazyField(object, "blah", "lazy", "x");
178 212
179 RegisterModule("test", 213 RegisterModule("test",
180 "var assert = requireNative('assert');" 214 "var assert = requireNative('assert');"
181 "assert.AssertTrue(object.blah == 5);"); 215 "assert.AssertTrue(object.blah == 5);");
182 module_system_->Require("test"); 216 module_system_->Require("test");
183 } 217 }
218
219 TEST_F(ModuleSystemTest, TestLazyFieldYieldingObject) {
220 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
221 RegisterModule("lazy",
222 "var object = {};"
223 "object.__defineGetter__('z', function() { return 1; });"
224 "object.x = 5;"
225 "object.y = function() { return 10; };"
226 "exports.object = object;");
227
228 v8::Handle<v8::Object> object = CreateGlobal("object");
229
230 module_system_->SetLazyField(object, "thing", "lazy", "object");
231
232 RegisterModule("test",
233 "var assert = requireNative('assert');"
234 "assert.AssertTrue(object.thing.x == 5);"
235 "assert.AssertTrue(object.thing.y() == 10);"
236 "assert.AssertTrue(object.thing.z == 1);"
237 );
238 module_system_->Require("test");
239 }
240
241 TEST_F(ModuleSystemTest, TestLazyFieldIsOnlyEvaledOnce) {
242 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
243 module_system_->RegisterNativeHandler(
244 "counter",
245 scoped_ptr<NativeHandler>(new CounterNatives()));
246 RegisterModule("lazy",
247 "requireNative('counter').Increment();"
248 "exports.x = 5;");
249
250 v8::Handle<v8::Object> object = CreateGlobal("object");
251
252 module_system_->SetLazyField(object, "x", "lazy", "x");
253
254 RegisterModule("test",
255 "var assert = requireNative('assert');"
256 "var counter = requireNative('counter');"
257 "assert.AssertTrue(counter.Get() == 0);"
258 "object.x;"
259 "assert.AssertTrue(counter.Get() == 1);"
260 "object.x;"
261 "assert.AssertTrue(counter.Get() == 1);");
262 module_system_->Require("test");
263 }
264
265 TEST_F(ModuleSystemTest, TestRequireNativesAfterLazyEvaluation) {
266 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
267 RegisterModule("lazy",
268 "exports.x = 5;");
269 v8::Handle<v8::Object> object = CreateGlobal("object");
270
271 module_system_->SetLazyField(object, "x", "lazy", "x");
272 RegisterModule("test",
273 "object.x;"
274 "requireNative('assert').AssertTrue(true);");
275 module_system_->Require("test");
276 }
277
278 TEST_F(ModuleSystemTest, TestTransitiveRequire) {
279 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
280 RegisterModule("dependency",
281 "exports.x = 5;");
282 RegisterModule("lazy",
283 "exports.output = require('dependency');");
284
285 v8::Handle<v8::Object> object = CreateGlobal("object");
286
287 module_system_->SetLazyField(object, "thing", "lazy", "output");
288
289 RegisterModule("test",
290 "var assert = requireNative('assert');"
291 "assert.AssertTrue(object.thing.x == 5);");
292 module_system_->Require("test");
293 }
294
295 TEST_F(ModuleSystemTest, TestModulesOnlyGetEvaledOnce) {
296 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
297 module_system_->RegisterNativeHandler(
298 "counter",
299 scoped_ptr<NativeHandler>(new CounterNatives()));
300
301 RegisterModule("incrementsWhenEvaled",
302 "requireNative('counter').Increment();");
303 RegisterModule("test",
304 "var assert = requireNative('assert');"
305 "var counter = requireNative('counter');"
306 "assert.AssertTrue(counter.Get() == 0);"
307 "require('incrementsWhenEvaled');"
308 "assert.AssertTrue(counter.Get() == 1);"
309 "require('incrementsWhenEvaled');"
310 "assert.AssertTrue(counter.Get() == 1);");
311
312 module_system_->Require("test");
313 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698