Home | History | Annotate | Download | only in extensions
      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 }
    263