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

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: rebase 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
« no previous file with comments | « chrome/renderer/module_system.cc ('k') | chrome/renderer/native_handler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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() : counter_(0) {
41 RouteFunction("Get", base::Bind(&CounterNatives::Get,
42 base::Unretained(this)));
43 RouteFunction("Increment", base::Bind(&CounterNatives::Increment,
44 base::Unretained(this)));
45 }
46
47 v8::Handle<v8::Value> Get(const v8::Arguments& args) {
48 return v8::Integer::New(counter_);
49 }
50
51 v8::Handle<v8::Value> Increment(const v8::Arguments& args) {
52 counter_++;
53 return v8::Undefined();
54 }
55
56 private:
57 int counter_;
58 };
59
38 class StringSourceMap : public ModuleSystem::SourceMap { 60 class StringSourceMap : public ModuleSystem::SourceMap {
39 public: 61 public:
40 StringSourceMap() {} 62 StringSourceMap() {}
41 virtual ~StringSourceMap() {} 63 virtual ~StringSourceMap() {}
42 64
43 v8::Handle<v8::Value> GetSource(const std::string& name) OVERRIDE { 65 v8::Handle<v8::Value> GetSource(const std::string& name) OVERRIDE {
44 if (source_map_.count(name) == 0) 66 if (source_map_.count(name) == 0)
45 return v8::Undefined(); 67 return v8::Undefined();
46 return v8::String::New(source_map_[name].c_str()); 68 return v8::String::New(source_map_[name].c_str());
47 } 69 }
48 70
49 bool Contains(const std::string& name) OVERRIDE { 71 bool Contains(const std::string& name) OVERRIDE {
50 return source_map_.count(name); 72 return source_map_.count(name);
51 } 73 }
52 74
53 void RegisterModule(const std::string& name, const std::string& source) { 75 void RegisterModule(const std::string& name, const std::string& source) {
54 source_map_[name] = source; 76 source_map_[name] = source;
55 } 77 }
56 78
57 private: 79 private:
58 std::map<std::string, std::string> source_map_; 80 std::map<std::string, std::string> source_map_;
59 }; 81 };
60 82
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 { 83 class ModuleSystemTest : public testing::Test {
81 public: 84 public:
82 ModuleSystemTest() 85 ModuleSystemTest()
83 : context_(v8::Context::New()), 86 : context_(v8::Context::New()),
84 source_map_(new StringSourceMap()) { 87 source_map_(new StringSourceMap()),
88 should_assertions_be_made_(true) {
85 context_->Enter(); 89 context_->Enter();
86 assert_natives_ = new AssertNatives(); 90 assert_natives_ = new AssertNatives();
87 module_system_.reset(new ModuleSystem(source_map_.get())); 91 module_system_.reset(new ModuleSystem(source_map_.get()));
88 module_system_->RegisterNativeHandler("assert", scoped_ptr<NativeHandler>( 92 module_system_->RegisterNativeHandler("assert", scoped_ptr<NativeHandler>(
89 assert_natives_)); 93 assert_natives_));
90 RegisterModule("add", "exports.Add = function(x, y) { return x + y; };"); 94 RegisterModule("add", "exports.Add = function(x, y) { return x + y; };");
91 } 95 }
92 96
93 ~ModuleSystemTest() { 97 ~ModuleSystemTest() {
94 context_->Exit(); 98 context_->Exit();
95 context_.Dispose(); 99 context_.Dispose();
96 } 100 }
97 101
98 void RegisterModule(const std::string& name, const std::string& code) { 102 void RegisterModule(const std::string& name, const std::string& code) {
99 source_map_->RegisterModule(name, code); 103 source_map_->RegisterModule(name, code);
100 } 104 }
101 105
102 virtual void TearDown() { 106 virtual void TearDown() {
103 // All tests must call a native function at least once. 107 ASSERT_FALSE(try_catch_.HasCaught());
104 ASSERT_TRUE(assert_natives_->native_function_called()); 108 // All tests must assert at least once unless otherwise specified.
109 ASSERT_EQ(should_assertions_be_made_,
110 assert_natives_->assertion_made());
105 ASSERT_FALSE(assert_natives_->failed()); 111 ASSERT_FALSE(assert_natives_->failed());
106 ASSERT_FALSE(try_catch_.HasCaught()); 112 }
113
114 void ExpectNoAssertionsMade() {
115 should_assertions_be_made_ = false;
116 }
117
118 v8::Handle<v8::Object> CreateGlobal(const std::string& name) {
119 v8::HandleScope handle_scope;
120 v8::Handle<v8::Object> object = v8::Object::New();
121 v8::Context::GetCurrent()->Global()->Set(v8::String::New(name.c_str()),
122 object);
123 return handle_scope.Close(object);
107 } 124 }
108 125
109 v8::Persistent<v8::Context> context_; 126 v8::Persistent<v8::Context> context_;
110 v8::HandleScope handle_scope_; 127 v8::HandleScope handle_scope_;
111 v8::TryCatch try_catch_; 128 v8::TryCatch try_catch_;
112 AssertNatives* assert_natives_; 129 AssertNatives* assert_natives_;
113 scoped_ptr<StringSourceMap> source_map_; 130 scoped_ptr<StringSourceMap> source_map_;
114 scoped_ptr<ModuleSystem> module_system_; 131 scoped_ptr<ModuleSystem> module_system_;
132 bool should_assertions_be_made_;
115 }; 133 };
116 134
117 TEST_F(ModuleSystemTest, TestRequire) { 135 TEST_F(ModuleSystemTest, TestRequire) {
136 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
118 RegisterModule("test", 137 RegisterModule("test",
119 "var Add = require('add').Add;" 138 "var Add = require('add').Add;"
120 "requireNative('assert').AssertTrue(Add(3, 5) == 8);"); 139 "requireNative('assert').AssertTrue(Add(3, 5) == 8);");
121 module_system_->Require("test"); 140 module_system_->Require("test");
122 } 141 }
123 142
124 TEST_F(ModuleSystemTest, TestNestedRequire) { 143 TEST_F(ModuleSystemTest, TestNestedRequire) {
144 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
125 RegisterModule("double", 145 RegisterModule("double",
126 "var Add = require('add').Add;" 146 "var Add = require('add').Add;"
127 "exports.Double = function(x) { return Add(x, x); };"); 147 "exports.Double = function(x) { return Add(x, x); };");
128 RegisterModule("test", 148 RegisterModule("test",
129 "var Double = require('double').Double;" 149 "var Double = require('double').Double;"
130 "requireNative('assert').AssertTrue(Double(3) == 6);"); 150 "requireNative('assert').AssertTrue(Double(3) == 6);");
131 module_system_->Require("test"); 151 module_system_->Require("test");
132 } 152 }
133 153
134 TEST_F(ModuleSystemTest, TestModuleInsulation) { 154 TEST_F(ModuleSystemTest, TestModuleInsulation) {
155 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
135 RegisterModule("x", 156 RegisterModule("x",
136 "var x = 10;" 157 "var x = 10;"
137 "exports.X = function() { return x; };"); 158 "exports.X = function() { return x; };");
138 RegisterModule("y", 159 RegisterModule("y",
139 "var x = 15;" 160 "var x = 15;"
140 "require('x');" 161 "require('x');"
141 "exports.Y = function() { return x; };"); 162 "exports.Y = function() { return x; };");
142 RegisterModule("test", 163 RegisterModule("test",
143 "var Y = require('y').Y;" 164 "var Y = require('y').Y;"
144 "var X = require('x').X;" 165 "var X = require('x').X;"
145 "var assert = requireNative('assert');" 166 "var assert = requireNative('assert');"
146 "assert.AssertTrue(!this.hasOwnProperty('x'));" 167 "assert.AssertTrue(!this.hasOwnProperty('x'));"
147 "assert.AssertTrue(Y() == 15);" 168 "assert.AssertTrue(Y() == 15);"
148 "assert.AssertTrue(X() == 10);"); 169 "assert.AssertTrue(X() == 10);");
149 module_system_->Require("test"); 170 module_system_->Require("test");
150 } 171 }
151 172
152 TEST_F(ModuleSystemTest, TestDisableNativesPreventsNativeModulesBeingLoaded) { 173 TEST_F(ModuleSystemTest, TestNativesAreDisabledOutsideANativesEnabledScope) {
153 module_system_->RegisterNativeHandler("disable",
154 scoped_ptr<NativeHandler>(
155 new DisableNativesHandler(module_system_.get())));
156 RegisterModule("test", 174 RegisterModule("test",
157 "var assert = requireNative('assert');" 175 "var assert;"
158 "var disable = requireNative('disable');"
159 "disable.DisableNatives();"
160 "var caught = false;"
161 "try {" 176 "try {"
162 " requireNative('assert');" 177 " assert = requireNative('assert');"
163 "} catch (e) {" 178 "} catch (e) {"
164 " caught = true;" 179 " caught = true;"
165 "}" 180 "}"
166 "assert.AssertTrue(caught);"); 181 "if (assert) {"
182 " assert.AssertTrue(true);"
183 "}");
167 module_system_->Require("test"); 184 module_system_->Require("test");
185 ExpectNoAssertionsMade();
186 }
187
188 TEST_F(ModuleSystemTest, TestNativesAreEnabledWithinANativesEnabledScope) {
189 RegisterModule("test",
190 "var assert = requireNative('assert');"
191 "assert.AssertTrue(true);");
192
193 {
194 ModuleSystem::NativesEnabledScope natives_enabled(module_system_.get());
195 {
196 ModuleSystem::NativesEnabledScope natives_enabled_inner(
197 module_system_.get());
198 }
199 module_system_->Require("test");
200 }
168 } 201 }
169 202
170 TEST_F(ModuleSystemTest, TestLazyField) { 203 TEST_F(ModuleSystemTest, TestLazyField) {
204 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
171 RegisterModule("lazy", 205 RegisterModule("lazy",
172 "exports.x = 5;"); 206 "exports.x = 5;");
173 207
174 v8::Handle<v8::Object> object = v8::Object::New(); 208 v8::Handle<v8::Object> object = CreateGlobal("object");
175 v8::Context::GetCurrent()->Global()->Set(v8::String::New("object"), object);
176 209
177 module_system_->SetLazyField(object, "blah", "lazy", "x"); 210 module_system_->SetLazyField(object, "blah", "lazy", "x");
178 211
179 RegisterModule("test", 212 RegisterModule("test",
180 "var assert = requireNative('assert');" 213 "var assert = requireNative('assert');"
181 "assert.AssertTrue(object.blah == 5);"); 214 "assert.AssertTrue(object.blah == 5);");
182 module_system_->Require("test"); 215 module_system_->Require("test");
183 } 216 }
217
218 TEST_F(ModuleSystemTest, TestLazyFieldYieldingObject) {
219 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
220 RegisterModule("lazy",
221 "var object = {};"
222 "object.__defineGetter__('z', function() { return 1; });"
223 "object.x = 5;"
224 "object.y = function() { return 10; };"
225 "exports.object = object;");
226
227 v8::Handle<v8::Object> object = CreateGlobal("object");
228
229 module_system_->SetLazyField(object, "thing", "lazy", "object");
230
231 RegisterModule("test",
232 "var assert = requireNative('assert');"
233 "assert.AssertTrue(object.thing.x == 5);"
234 "assert.AssertTrue(object.thing.y() == 10);"
235 "assert.AssertTrue(object.thing.z == 1);"
236 );
237 module_system_->Require("test");
238 }
239
240 TEST_F(ModuleSystemTest, TestLazyFieldIsOnlyEvaledOnce) {
241 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
242 module_system_->RegisterNativeHandler(
243 "counter",
244 scoped_ptr<NativeHandler>(new CounterNatives()));
245 RegisterModule("lazy",
246 "requireNative('counter').Increment();"
247 "exports.x = 5;");
248
249 v8::Handle<v8::Object> object = CreateGlobal("object");
250
251 module_system_->SetLazyField(object, "x", "lazy", "x");
252
253 RegisterModule("test",
254 "var assert = requireNative('assert');"
255 "var counter = requireNative('counter');"
256 "assert.AssertTrue(counter.Get() == 0);"
257 "object.x;"
258 "assert.AssertTrue(counter.Get() == 1);"
259 "object.x;"
260 "assert.AssertTrue(counter.Get() == 1);");
261 module_system_->Require("test");
262 }
263
264 TEST_F(ModuleSystemTest, TestRequireNativesAfterLazyEvaluation) {
265 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
266 RegisterModule("lazy",
267 "exports.x = 5;");
268 v8::Handle<v8::Object> object = CreateGlobal("object");
269
270 module_system_->SetLazyField(object, "x", "lazy", "x");
271 RegisterModule("test",
272 "object.x;"
273 "requireNative('assert').AssertTrue(true);");
274 module_system_->Require("test");
275 }
276
277 TEST_F(ModuleSystemTest, TestTransitiveRequire) {
278 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
279 RegisterModule("dependency",
280 "exports.x = 5;");
281 RegisterModule("lazy",
282 "exports.output = require('dependency');");
283
284 v8::Handle<v8::Object> object = CreateGlobal("object");
285
286 module_system_->SetLazyField(object, "thing", "lazy", "output");
287
288 RegisterModule("test",
289 "var assert = requireNative('assert');"
290 "assert.AssertTrue(object.thing.x == 5);");
291 module_system_->Require("test");
292 }
293
294 TEST_F(ModuleSystemTest, TestModulesOnlyGetEvaledOnce) {
295 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
296 module_system_->RegisterNativeHandler(
297 "counter",
298 scoped_ptr<NativeHandler>(new CounterNatives()));
299
300 RegisterModule("incrementsWhenEvaled",
301 "requireNative('counter').Increment();");
302 RegisterModule("test",
303 "var assert = requireNative('assert');"
304 "var counter = requireNative('counter');"
305 "assert.AssertTrue(counter.Get() == 0);"
306 "require('incrementsWhenEvaled');"
307 "assert.AssertTrue(counter.Get() == 1);"
308 "require('incrementsWhenEvaled');"
309 "assert.AssertTrue(counter.Get() == 1);");
310
311 module_system_->Require("test");
312 }
OLDNEW
« no previous file with comments | « chrome/renderer/module_system.cc ('k') | chrome/renderer/native_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698