OLD | NEW |
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 "chrome/renderer/module_system.h" | 8 #include "chrome/renderer/module_system.h" |
| 9 #include "chrome/renderer/source_map.h" |
8 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
9 | 11 |
10 #include <map> | 12 #include <map> |
11 #include <string> | 13 #include <string> |
12 | 14 |
| 15 // Native JS functions for doing asserts. |
13 class AssertNatives : public NativeHandler { | 16 class AssertNatives : public NativeHandler { |
14 public: | 17 public: |
15 AssertNatives() | 18 AssertNatives() |
16 : native_function_called_(false), | 19 : native_function_called_(false), |
17 failed_(false) { | 20 failed_(false) { |
18 RouteFunction("AssertTrue", base::Bind(&AssertNatives::AssertTrue, | 21 RouteFunction("AssertTrue", base::Bind(&AssertNatives::AssertTrue, |
19 base::Unretained(this))); | 22 base::Unretained(this))); |
20 } | 23 } |
21 | 24 |
22 bool native_function_called() { return native_function_called_; } | 25 bool native_function_called() { return native_function_called_; } |
23 bool failed() { return failed_; } | 26 bool failed() { return failed_; } |
24 | 27 |
25 v8::Handle<v8::Value> AssertTrue(const v8::Arguments& args) { | 28 v8::Handle<v8::Value> AssertTrue(const v8::Arguments& args) { |
26 native_function_called_ = true; | 29 native_function_called_ = true; |
27 failed_ = failed_ || !args[0]->ToBoolean()->Value(); | 30 failed_ = failed_ || !args[0]->ToBoolean()->Value(); |
28 return v8::Undefined(); | 31 return v8::Undefined(); |
29 } | 32 } |
30 | 33 |
31 private: | 34 private: |
32 bool native_function_called_; | 35 bool native_function_called_; |
33 bool failed_; | 36 bool failed_; |
34 }; | 37 }; |
35 | 38 |
| 39 class StringSourceMap : public SourceMap { |
| 40 public: |
| 41 StringSourceMap() {} |
| 42 |
| 43 v8::Handle<v8::Value> GetSource(const std::string& name) OVERRIDE { |
| 44 if (source_map_.count(name) == 0) |
| 45 return v8::Undefined(); |
| 46 return v8::String::New(source_map_[name].c_str()); |
| 47 } |
| 48 |
| 49 bool Contains(const std::string& name) OVERRIDE { |
| 50 return source_map_.count(name); |
| 51 } |
| 52 |
| 53 void RegisterModule(const std::string& name, const std::string& source) { |
| 54 source_map_[name] = source; |
| 55 } |
| 56 |
| 57 private: |
| 58 std::map<std::string, std::string> source_map_; |
| 59 }; |
| 60 |
| 61 // Native JS functions for disabling injection in ModuleSystem. |
| 62 class DisableInjectionHandler : public NativeHandler { |
| 63 public: |
| 64 explicit DisableInjectionHandler(ModuleSystem* module_system) |
| 65 : module_system_(module_system) { |
| 66 RouteFunction("DisableInjection", |
| 67 base::Bind(&DisableInjectionHandler::DisableInjection, |
| 68 base::Unretained(this))); |
| 69 } |
| 70 |
| 71 v8::Handle<v8::Value> DisableInjection(const v8::Arguments& args) { |
| 72 module_system_->DisableInjection(); |
| 73 return v8::Undefined(); |
| 74 } |
| 75 |
| 76 private: |
| 77 ModuleSystem* module_system_; |
| 78 }; |
| 79 |
36 class ModuleSystemTest : public testing::Test { | 80 class ModuleSystemTest : public testing::Test { |
37 public: | 81 public: |
38 ModuleSystemTest() | 82 ModuleSystemTest() |
39 : context_(v8::Context::New()), | 83 : context_(v8::Context::New()), |
40 assert_natives_(new AssertNatives()) { | 84 handle_scope_(), |
| 85 assert_natives_(new AssertNatives()), |
| 86 source_map_(new StringSourceMap()), |
| 87 module_system_(new ModuleSystem(source_map_)) { |
41 context_->Enter(); | 88 context_->Enter(); |
42 source_map_["add"] = "exports.Add = function(x, y) { return x + y; };"; | |
43 module_system_.reset(new ModuleSystem(&source_map_)); | |
44 module_system_->RegisterNativeHandler("assert", scoped_ptr<NativeHandler>( | 89 module_system_->RegisterNativeHandler("assert", scoped_ptr<NativeHandler>( |
45 assert_natives_)); | 90 assert_natives_)); |
| 91 RegisterModule("add", "exports.Add = function(x, y) { return x + y; };"); |
46 } | 92 } |
47 | 93 |
48 ~ModuleSystemTest() { | 94 ~ModuleSystemTest() { |
49 context_.Dispose(); | 95 context_.Dispose(); |
50 } | 96 } |
51 | 97 |
| 98 void RegisterModule(const std::string& name, const std::string& code) { |
| 99 source_map_->RegisterModule(name, code); |
| 100 } |
| 101 |
52 virtual void TearDown() { | 102 virtual void TearDown() { |
53 // All tests must call a native function at least once. | 103 // All tests must call a native function at least once. |
54 ASSERT_TRUE(assert_natives_->native_function_called()); | 104 ASSERT_TRUE(assert_natives_->native_function_called()); |
55 ASSERT_FALSE(assert_natives_->failed()); | 105 ASSERT_FALSE(assert_natives_->failed()); |
56 ASSERT_FALSE(try_catch_.HasCaught()); | 106 ASSERT_FALSE(try_catch_.HasCaught()); |
57 } | 107 } |
58 | 108 |
| 109 v8::Persistent<v8::Context> context_; |
59 v8::HandleScope handle_scope_; | 110 v8::HandleScope handle_scope_; |
60 v8::TryCatch try_catch_; | 111 v8::TryCatch try_catch_; |
61 v8::Persistent<v8::Context> context_; | |
62 AssertNatives* assert_natives_; | 112 AssertNatives* assert_natives_; |
63 std::map<std::string, std::string> source_map_; | 113 StringSourceMap* source_map_; |
64 scoped_ptr<ModuleSystem> module_system_; | 114 scoped_ptr<ModuleSystem> module_system_; |
65 }; | 115 }; |
66 | 116 |
67 TEST_F(ModuleSystemTest, TestRequire) { | 117 TEST_F(ModuleSystemTest, TestRequire) { |
68 source_map_["test"] = | 118 RegisterModule("test", |
69 "var Add = require('add').Add;" | 119 "var Add = require('add').Add;" |
70 "requireNative('assert').AssertTrue(Add(3, 5) == 8);"; | 120 "requireNative('assert').AssertTrue(Add(3, 5) == 8);"); |
71 module_system_->Require("test"); | 121 module_system_->Require("test"); |
72 } | 122 } |
73 | 123 |
74 TEST_F(ModuleSystemTest, TestNestedRequire) { | 124 TEST_F(ModuleSystemTest, TestNestedRequire) { |
75 source_map_["double"] = | 125 RegisterModule("double", |
76 "var Add = require('add').Add;" | 126 "var Add = require('add').Add;" |
77 "exports.Double = function(x) { return Add(x, x); };"; | 127 "exports.Double = function(x) { return Add(x, x); };"); |
78 source_map_["test"] = | 128 RegisterModule("test", |
79 "var Double = require('double').Double;" | 129 "var Double = require('double').Double;" |
80 "requireNative('assert').AssertTrue(Double(3) == 6);"; | 130 "requireNative('assert').AssertTrue(Double(3) == 6);"); |
81 module_system_->Require("test"); | 131 module_system_->Require("test"); |
82 } | 132 } |
83 | 133 |
84 TEST_F(ModuleSystemTest, TestModuleInsulation) { | 134 TEST_F(ModuleSystemTest, TestModuleInsulation) { |
85 source_map_["x"] = | 135 RegisterModule("x", |
86 "var x = 10;" | 136 "var x = 10;" |
87 "exports.X = function() { return x; };"; | 137 "exports.X = function() { return x; };"); |
88 source_map_["y"] = | 138 RegisterModule("y", |
89 "var x = 15;" | 139 "var x = 15;" |
90 "require('x');" | 140 "require('x');" |
91 "exports.Y = function() { return x; };"; | 141 "exports.Y = function() { return x; };"); |
92 source_map_["test"] = | 142 RegisterModule("test", |
93 "var Y = require('y').Y;" | 143 "var Y = require('y').Y;" |
94 "var X = require('x').X;" | 144 "var X = require('x').X;" |
95 "var assert = requireNative('assert');" | 145 "var assert = requireNative('assert');" |
96 "assert.AssertTrue(!this.hasOwnProperty('x'));" | 146 "assert.AssertTrue(!this.hasOwnProperty('x'));" |
97 "assert.AssertTrue(Y() == 15);" | 147 "assert.AssertTrue(Y() == 15);" |
98 "assert.AssertTrue(X() == 10);"; | 148 "assert.AssertTrue(X() == 10);"); |
99 module_system_->Require("test"); | 149 module_system_->Require("test"); |
100 } | 150 } |
| 151 |
| 152 TEST_F(ModuleSystemTest, TestDisableInjectionPreventsNewModulesBeingLoaded) { |
| 153 module_system_->RegisterNativeHandler("disable", |
| 154 scoped_ptr<NativeHandler>( |
| 155 new DisableInjectionHandler(module_system_.get()))); |
| 156 RegisterModule("test", |
| 157 "var assert = requireNative('assert');" |
| 158 "var disable = requireNative('disable');" |
| 159 "disable.DisableInjection();" |
| 160 "var caught = false;" |
| 161 "try {" |
| 162 " require('unused-module');" |
| 163 "} catch (e) {" |
| 164 " caught = true;" |
| 165 "}" |
| 166 "assert.AssertTrue(caught);"); |
| 167 module_system_->Require("test"); |
| 168 } |
| 169 |
| 170 TEST_F(ModuleSystemTest, TestDisableInjectionPreventsNativeModulesBeingLoaded) { |
| 171 module_system_->RegisterNativeHandler("disable", |
| 172 scoped_ptr<NativeHandler>( |
| 173 new DisableInjectionHandler(module_system_.get()))); |
| 174 RegisterModule("test", |
| 175 "var assert = requireNative('assert');" |
| 176 "var disable = requireNative('disable');" |
| 177 "disable.DisableInjection();" |
| 178 "var caught = false;" |
| 179 "try {" |
| 180 " requireNative('assert');" |
| 181 "} catch (e) {" |
| 182 " caught = true;" |
| 183 "}" |
| 184 "assert.AssertTrue(caught);"); |
| 185 module_system_->Require("test"); |
| 186 } |
OLD | NEW |