- add sources.
[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 "chrome/test/base/module_system_test.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "chrome/renderer/extensions/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(module_system_.get());
54   TestExceptionHandler* handler = new TestExceptionHandler;
55   scoped_ptr<ModuleSystem::ExceptionHandler> scoped_handler(handler);
56   ASSERT_FALSE(handler->handled_exception());
57   module_system_->SetExceptionHandlerForTest(scoped_handler.Pass());
58
59   RegisterModule("test", "throw 'hi';");
60   module_system_->Require("test");
61   ASSERT_TRUE(handler->handled_exception());
62
63   ExpectNoAssertionsMade();
64 }
65
66 TEST_F(ModuleSystemTest, TestRequire) {
67   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
68   RegisterModule("add", "exports.Add = function(x, y) { return x + y; };");
69   RegisterModule("test",
70       "var Add = require('add').Add;"
71       "requireNative('assert').AssertTrue(Add(3, 5) == 8);");
72   module_system_->Require("test");
73 }
74
75 TEST_F(ModuleSystemTest, TestNestedRequire) {
76   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
77   RegisterModule("add", "exports.Add = function(x, y) { return x + y; };");
78   RegisterModule("double",
79       "var Add = require('add').Add;"
80       "exports.Double = function(x) { return Add(x, x); };");
81   RegisterModule("test",
82       "var Double = require('double').Double;"
83       "requireNative('assert').AssertTrue(Double(3) == 6);");
84   module_system_->Require("test");
85 }
86
87 TEST_F(ModuleSystemTest, TestModuleInsulation) {
88   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
89   RegisterModule("x",
90       "var x = 10;"
91       "exports.X = function() { return x; };");
92   RegisterModule("y",
93       "var x = 15;"
94       "require('x');"
95       "exports.Y = function() { return x; };");
96   RegisterModule("test",
97       "var Y = require('y').Y;"
98       "var X = require('x').X;"
99       "var assert = requireNative('assert');"
100       "assert.AssertTrue(!this.hasOwnProperty('x'));"
101       "assert.AssertTrue(Y() == 15);"
102       "assert.AssertTrue(X() == 10);");
103   module_system_->Require("test");
104 }
105
106 TEST_F(ModuleSystemTest, TestNativesAreDisabledOutsideANativesEnabledScope) {
107   RegisterModule("test",
108       "var assert;"
109       "try {"
110       "  assert = requireNative('assert');"
111       "} catch (e) {"
112       "  var caught = true;"
113       "}"
114       "if (assert) {"
115       "  assert.AssertTrue(true);"
116       "}");
117   module_system_->Require("test");
118   ExpectNoAssertionsMade();
119 }
120
121 TEST_F(ModuleSystemTest, TestNativesAreEnabledWithinANativesEnabledScope) {
122   RegisterModule("test",
123       "var assert = requireNative('assert');"
124       "assert.AssertTrue(true);");
125
126   {
127     ModuleSystem::NativesEnabledScope natives_enabled(module_system_.get());
128     {
129       ModuleSystem::NativesEnabledScope natives_enabled_inner(
130           module_system_.get());
131     }
132     module_system_->Require("test");
133   }
134 }
135
136 TEST_F(ModuleSystemTest, TestLazyField) {
137   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
138   RegisterModule("lazy",
139       "exports.x = 5;");
140
141   v8::Handle<v8::Object> object = CreateGlobal("object");
142
143   module_system_->SetLazyField(object, "blah", "lazy", "x");
144
145   RegisterModule("test",
146       "var assert = requireNative('assert');"
147       "assert.AssertTrue(object.blah == 5);");
148   module_system_->Require("test");
149 }
150
151 TEST_F(ModuleSystemTest, TestLazyFieldYieldingObject) {
152   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
153   RegisterModule("lazy",
154       "var object = {};"
155       "object.__defineGetter__('z', function() { return 1; });"
156       "object.x = 5;"
157       "object.y = function() { return 10; };"
158       "exports.object = object;");
159
160   v8::Handle<v8::Object> object = CreateGlobal("object");
161
162   module_system_->SetLazyField(object, "thing", "lazy", "object");
163
164   RegisterModule("test",
165       "var assert = requireNative('assert');"
166       "assert.AssertTrue(object.thing.x == 5);"
167       "assert.AssertTrue(object.thing.y() == 10);"
168       "assert.AssertTrue(object.thing.z == 1);"
169       );
170   module_system_->Require("test");
171 }
172
173 TEST_F(ModuleSystemTest, TestLazyFieldIsOnlyEvaledOnce) {
174   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
175   module_system_->RegisterNativeHandler(
176       "counter",
177       scoped_ptr<NativeHandler>(new CounterNatives(context_.get())));
178   RegisterModule("lazy",
179       "requireNative('counter').Increment();"
180       "exports.x = 5;");
181
182   v8::Handle<v8::Object> object = CreateGlobal("object");
183
184   module_system_->SetLazyField(object, "x", "lazy", "x");
185
186   RegisterModule("test",
187       "var assert = requireNative('assert');"
188       "var counter = requireNative('counter');"
189       "assert.AssertTrue(counter.Get() == 0);"
190       "object.x;"
191       "assert.AssertTrue(counter.Get() == 1);"
192       "object.x;"
193       "assert.AssertTrue(counter.Get() == 1);");
194   module_system_->Require("test");
195 }
196
197 TEST_F(ModuleSystemTest, TestRequireNativesAfterLazyEvaluation) {
198   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
199   RegisterModule("lazy",
200       "exports.x = 5;");
201   v8::Handle<v8::Object> object = CreateGlobal("object");
202
203   module_system_->SetLazyField(object, "x", "lazy", "x");
204   RegisterModule("test",
205       "object.x;"
206       "requireNative('assert').AssertTrue(true);");
207   module_system_->Require("test");
208 }
209
210 TEST_F(ModuleSystemTest, TestTransitiveRequire) {
211   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
212   RegisterModule("dependency",
213       "exports.x = 5;");
214   RegisterModule("lazy",
215       "exports.output = require('dependency');");
216
217   v8::Handle<v8::Object> object = CreateGlobal("object");
218
219   module_system_->SetLazyField(object, "thing", "lazy", "output");
220
221   RegisterModule("test",
222       "var assert = requireNative('assert');"
223       "assert.AssertTrue(object.thing.x == 5);");
224   module_system_->Require("test");
225 }
226
227 TEST_F(ModuleSystemTest, TestModulesOnlyGetEvaledOnce) {
228   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
229   module_system_->RegisterNativeHandler(
230       "counter",
231       scoped_ptr<NativeHandler>(new CounterNatives(context_.get())));
232
233   RegisterModule("incrementsWhenEvaled",
234       "requireNative('counter').Increment();");
235   RegisterModule("test",
236       "var assert = requireNative('assert');"
237       "var counter = requireNative('counter');"
238       "assert.AssertTrue(counter.Get() == 0);"
239       "require('incrementsWhenEvaled');"
240       "assert.AssertTrue(counter.Get() == 1);"
241       "require('incrementsWhenEvaled');"
242       "assert.AssertTrue(counter.Get() == 1);");
243
244   module_system_->Require("test");
245 }
246
247 TEST_F(ModuleSystemTest, TestOverrideNativeHandler) {
248   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
249   OverrideNativeHandler("assert", "exports.AssertTrue = function() {};");
250   RegisterModule("test", "requireNative('assert').AssertTrue(true);");
251   ExpectNoAssertionsMade();
252   module_system_->Require("test");
253 }
254
255 TEST_F(ModuleSystemTest, TestOverrideNonExistentNativeHandler) {
256   ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system_.get());
257   OverrideNativeHandler("thing", "exports.x = 5;");
258   RegisterModule("test",
259       "var assert = requireNative('assert');"
260       "assert.AssertTrue(requireNative('thing').x == 5);");
261   module_system_->Require("test");
262 }