Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / extensions / module_system_unittest.cc
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
3 // found in the LICENSE file.
4
5 #include "base/memory/scoped_ptr.h"
6 #include "chrome/test/base/module_system_test.h"
7 #include "extensions/renderer/module_system.h"
8
9 // TODO(cduvall/kalman): Put this file in extensions namespace.
10 using extensions::ModuleSystem;
11 using extensions::NativeHandler;
12 using extensions::ObjectBackedNativeHandler;
13
14 class CounterNatives : public ObjectBackedNativeHandler {
15  public:
16   explicit CounterNatives(extensions::ChromeV8Context* context)
17       : ObjectBackedNativeHandler(context), counter_(0) {
18     RouteFunction("Get", base::Bind(&CounterNatives::Get,
19         base::Unretained(this)));
20     RouteFunction("Increment", base::Bind(&CounterNatives::Increment,
21         base::Unretained(this)));
22   }
23
24   void Get(const v8::FunctionCallbackInfo<v8::Value>& args) {
25     args.GetReturnValue().Set(static_cast<int32_t>(counter_));
26   }
27
28   void Increment(const v8::FunctionCallbackInfo<v8::Value>& args) {
29     counter_++;
30   }
31
32  private:
33   int counter_;
34 };
35
36 class TestExceptionHandler : public ModuleSystem::ExceptionHandler {
37  public:
38   TestExceptionHandler()
39       : handled_exception_(false) {
40   }
41
42   virtual void HandleUncaughtException(const v8::TryCatch& try_catch) OVERRIDE {
43     handled_exception_ = true;
44   }
45
46   bool handled_exception() const { return handled_exception_; }
47
48  private:
49   bool handled_exception_;
50 };
51
52 TEST_F(ModuleSystemTest, TestExceptionHandling) {
53   ModuleSystem::NativesEnabledScope natives_enabled_scope(
54       context_->module_system());
55   TestExceptionHandler* handler = new TestExceptionHandler;
56   scoped_ptr<ModuleSystem::ExceptionHandler> scoped_handler(handler);
57   ASSERT_FALSE(handler->handled_exception());
58   context_->module_system()->SetExceptionHandlerForTest(scoped_handler.Pass());
59
60   RegisterModule("test", "throw 'hi';");
61   context_->module_system()->Require("test");
62   ASSERT_TRUE(handler->handled_exception());
63
64   ExpectNoAssertionsMade();
65 }
66
67 TEST_F(ModuleSystemTest, TestRequire) {
68   ModuleSystem::NativesEnabledScope natives_enabled_scope(
69       context_->module_system());
70   RegisterModule("add", "exports.Add = function(x, y) { return x + y; };");
71   RegisterModule("test",
72       "var Add = require('add').Add;"
73       "requireNative('assert').AssertTrue(Add(3, 5) == 8);");
74   context_->module_system()->Require("test");
75 }
76
77 TEST_F(ModuleSystemTest, TestNestedRequire) {
78   ModuleSystem::NativesEnabledScope natives_enabled_scope(
79       context_->module_system());
80   RegisterModule("add", "exports.Add = function(x, y) { return x + y; };");
81   RegisterModule("double",
82       "var Add = require('add').Add;"
83       "exports.Double = function(x) { return Add(x, x); };");
84   RegisterModule("test",
85       "var Double = require('double').Double;"
86       "requireNative('assert').AssertTrue(Double(3) == 6);");
87   context_->module_system()->Require("test");
88 }
89
90 TEST_F(ModuleSystemTest, TestModuleInsulation) {
91   ModuleSystem::NativesEnabledScope natives_enabled_scope(
92       context_->module_system());
93   RegisterModule("x",
94       "var x = 10;"
95       "exports.X = function() { return x; };");
96   RegisterModule("y",
97       "var x = 15;"
98       "require('x');"
99       "exports.Y = function() { return x; };");
100   RegisterModule("test",
101       "var Y = require('y').Y;"
102       "var X = require('x').X;"
103       "var assert = requireNative('assert');"
104       "assert.AssertTrue(!this.hasOwnProperty('x'));"
105       "assert.AssertTrue(Y() == 15);"
106       "assert.AssertTrue(X() == 10);");
107   context_->module_system()->Require("test");
108 }
109
110 TEST_F(ModuleSystemTest, TestNativesAreDisabledOutsideANativesEnabledScope) {
111   RegisterModule("test",
112       "var assert;"
113       "try {"
114       "  assert = requireNative('assert');"
115       "} catch (e) {"
116       "  var caught = true;"
117       "}"
118       "if (assert) {"
119       "  assert.AssertTrue(true);"
120       "}");
121   context_->module_system()->Require("test");
122   ExpectNoAssertionsMade();
123 }
124
125 TEST_F(ModuleSystemTest, TestNativesAreEnabledWithinANativesEnabledScope) {
126   RegisterModule("test",
127       "var assert = requireNative('assert');"
128       "assert.AssertTrue(true);");
129
130   {
131     ModuleSystem::NativesEnabledScope natives_enabled(
132         context_->module_system());
133     {
134       ModuleSystem::NativesEnabledScope natives_enabled_inner(
135           context_->module_system());
136     }
137     context_->module_system()->Require("test");
138   }
139 }
140
141 TEST_F(ModuleSystemTest, TestLazyField) {
142   ModuleSystem::NativesEnabledScope natives_enabled_scope(
143       context_->module_system());
144   RegisterModule("lazy",
145       "exports.x = 5;");
146
147   v8::Handle<v8::Object> object = CreateGlobal("object");
148
149   context_->module_system()->SetLazyField(object, "blah", "lazy", "x");
150
151   RegisterModule("test",
152       "var assert = requireNative('assert');"
153       "assert.AssertTrue(object.blah == 5);");
154   context_->module_system()->Require("test");
155 }
156
157 TEST_F(ModuleSystemTest, TestLazyFieldYieldingObject) {
158   ModuleSystem::NativesEnabledScope natives_enabled_scope(
159       context_->module_system());
160   RegisterModule("lazy",
161       "var object = {};"
162       "object.__defineGetter__('z', function() { return 1; });"
163       "object.x = 5;"
164       "object.y = function() { return 10; };"
165       "exports.object = object;");
166
167   v8::Handle<v8::Object> object = CreateGlobal("object");
168
169   context_->module_system()->SetLazyField(object, "thing", "lazy", "object");
170
171   RegisterModule("test",
172       "var assert = requireNative('assert');"
173       "assert.AssertTrue(object.thing.x == 5);"
174       "assert.AssertTrue(object.thing.y() == 10);"
175       "assert.AssertTrue(object.thing.z == 1);"
176       );
177   context_->module_system()->Require("test");
178 }
179
180 TEST_F(ModuleSystemTest, TestLazyFieldIsOnlyEvaledOnce) {
181   ModuleSystem::NativesEnabledScope natives_enabled_scope(
182       context_->module_system());
183   context_->module_system()->RegisterNativeHandler(
184       "counter",
185       scoped_ptr<NativeHandler>(new CounterNatives(context_.get())));
186   RegisterModule("lazy",
187       "requireNative('counter').Increment();"
188       "exports.x = 5;");
189
190   v8::Handle<v8::Object> object = CreateGlobal("object");
191
192   context_->module_system()->SetLazyField(object, "x", "lazy", "x");
193
194   RegisterModule("test",
195       "var assert = requireNative('assert');"
196       "var counter = requireNative('counter');"
197       "assert.AssertTrue(counter.Get() == 0);"
198       "object.x;"
199       "assert.AssertTrue(counter.Get() == 1);"
200       "object.x;"
201       "assert.AssertTrue(counter.Get() == 1);");
202   context_->module_system()->Require("test");
203 }
204
205 TEST_F(ModuleSystemTest, TestRequireNativesAfterLazyEvaluation) {
206   ModuleSystem::NativesEnabledScope natives_enabled_scope(
207       context_->module_system());
208   RegisterModule("lazy",
209       "exports.x = 5;");
210   v8::Handle<v8::Object> object = CreateGlobal("object");
211
212   context_->module_system()->SetLazyField(object, "x", "lazy", "x");
213   RegisterModule("test",
214       "object.x;"
215       "requireNative('assert').AssertTrue(true);");
216   context_->module_system()->Require("test");
217 }
218
219 TEST_F(ModuleSystemTest, TestTransitiveRequire) {
220   ModuleSystem::NativesEnabledScope natives_enabled_scope(
221       context_->module_system());
222   RegisterModule("dependency",
223       "exports.x = 5;");
224   RegisterModule("lazy",
225       "exports.output = require('dependency');");
226
227   v8::Handle<v8::Object> object = CreateGlobal("object");
228
229   context_->module_system()->SetLazyField(object, "thing", "lazy", "output");
230
231   RegisterModule("test",
232       "var assert = requireNative('assert');"
233       "assert.AssertTrue(object.thing.x == 5);");
234   context_->module_system()->Require("test");
235 }
236
237 TEST_F(ModuleSystemTest, TestModulesOnlyGetEvaledOnce) {
238   ModuleSystem::NativesEnabledScope natives_enabled_scope(
239       context_->module_system());
240   context_->module_system()->RegisterNativeHandler(
241       "counter",
242       scoped_ptr<NativeHandler>(new CounterNatives(context_.get())));
243
244   RegisterModule("incrementsWhenEvaled",
245       "requireNative('counter').Increment();");
246   RegisterModule("test",
247       "var assert = requireNative('assert');"
248       "var counter = requireNative('counter');"
249       "assert.AssertTrue(counter.Get() == 0);"
250       "require('incrementsWhenEvaled');"
251       "assert.AssertTrue(counter.Get() == 1);"
252       "require('incrementsWhenEvaled');"
253       "assert.AssertTrue(counter.Get() == 1);");
254
255   context_->module_system()->Require("test");
256 }
257
258 TEST_F(ModuleSystemTest, TestOverrideNativeHandler) {
259   ModuleSystem::NativesEnabledScope natives_enabled_scope(
260       context_->module_system());
261   OverrideNativeHandler("assert", "exports.AssertTrue = function() {};");
262   RegisterModule("test", "requireNative('assert').AssertTrue(true);");
263   ExpectNoAssertionsMade();
264   context_->module_system()->Require("test");
265 }
266
267 TEST_F(ModuleSystemTest, TestOverrideNonExistentNativeHandler) {
268   ModuleSystem::NativesEnabledScope natives_enabled_scope(
269       context_->module_system());
270   OverrideNativeHandler("thing", "exports.x = 5;");
271   RegisterModule("test",
272       "var assert = requireNative('assert');"
273       "assert.AssertTrue(requireNative('thing').x == 5);");
274   context_->module_system()->Require("test");
275 }