Move ModuleSystemTest and the tests that use it into extensions/.

Review URL: https://codereview.chromium.org/375243002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283580 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/extensions/renderer/module_system_test.cc b/extensions/renderer/module_system_test.cc
new file mode 100644
index 0000000..13c8335
--- /dev/null
+++ b/extensions/renderer/module_system_test.cc
@@ -0,0 +1,241 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/renderer/module_system_test.h"
+
+#include <map>
+#include <string>
+
+#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/lazy_instance.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
+#include "base/stl_util.h"
+#include "base/strings/string_piece.h"
+#include "extensions/common/extension_paths.h"
+#include "extensions/renderer/logging_native_handler.h"
+#include "extensions/renderer/object_backed_native_handler.h"
+#include "extensions/renderer/safe_builtins.h"
+#include "extensions/renderer/utils_native_handler.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace extensions {
+namespace {
+
+class FailsOnException : public ModuleSystem::ExceptionHandler {
+ public:
+  virtual void HandleUncaughtException(const v8::TryCatch& try_catch) OVERRIDE {
+    FAIL() << "Uncaught exception: " << CreateExceptionString(try_catch);
+  }
+};
+
+class V8ExtensionConfigurator {
+ public:
+  V8ExtensionConfigurator()
+      : safe_builtins_(SafeBuiltins::CreateV8Extension()),
+        names_(1, safe_builtins_->name()),
+        configuration_(
+            new v8::ExtensionConfiguration(static_cast<int>(names_.size()),
+                                           vector_as_array(&names_))) {
+    v8::RegisterExtension(safe_builtins_.get());
+  }
+
+  v8::ExtensionConfiguration* GetConfiguration() {
+    return configuration_.get();
+  }
+
+ private:
+  scoped_ptr<v8::Extension> safe_builtins_;
+  std::vector<const char*> names_;
+  scoped_ptr<v8::ExtensionConfiguration> configuration_;
+};
+
+base::LazyInstance<V8ExtensionConfigurator>::Leaky g_v8_extension_configurator =
+    LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+// Native JS functions for doing asserts.
+class ModuleSystemTestEnvironment::AssertNatives
+    : public ObjectBackedNativeHandler {
+ public:
+  explicit AssertNatives(ScriptContext* context)
+      : ObjectBackedNativeHandler(context),
+        assertion_made_(false),
+        failed_(false) {
+    RouteFunction(
+        "AssertTrue",
+        base::Bind(&AssertNatives::AssertTrue, base::Unretained(this)));
+    RouteFunction(
+        "AssertFalse",
+        base::Bind(&AssertNatives::AssertFalse, base::Unretained(this)));
+  }
+
+  bool assertion_made() { return assertion_made_; }
+  bool failed() { return failed_; }
+
+  void AssertTrue(const v8::FunctionCallbackInfo<v8::Value>& args) {
+    CHECK_EQ(1, args.Length());
+    assertion_made_ = true;
+    failed_ = failed_ || !args[0]->ToBoolean()->Value();
+  }
+
+  void AssertFalse(const v8::FunctionCallbackInfo<v8::Value>& args) {
+    CHECK_EQ(1, args.Length());
+    assertion_made_ = true;
+    failed_ = failed_ || args[0]->ToBoolean()->Value();
+  }
+
+ private:
+  bool assertion_made_;
+  bool failed_;
+};
+
+// Source map that operates on std::strings.
+class ModuleSystemTestEnvironment::StringSourceMap
+    : public ModuleSystem::SourceMap {
+ public:
+  StringSourceMap() {}
+  virtual ~StringSourceMap() {}
+
+  virtual v8::Handle<v8::Value> GetSource(v8::Isolate* isolate,
+                                          const std::string& name) OVERRIDE {
+    if (source_map_.count(name) == 0)
+      return v8::Undefined(isolate);
+    return v8::String::NewFromUtf8(isolate, source_map_[name].c_str());
+  }
+
+  virtual bool Contains(const std::string& name) OVERRIDE {
+    return source_map_.count(name);
+  }
+
+  void RegisterModule(const std::string& name, const std::string& source) {
+    CHECK_EQ(0u, source_map_.count(name)) << "Module " << name << " not found";
+    source_map_[name] = source;
+  }
+
+ private:
+  std::map<std::string, std::string> source_map_;
+};
+
+ModuleSystemTestEnvironment::ModuleSystemTestEnvironment(
+    gin::IsolateHolder* isolate_holder)
+    : isolate_holder_(isolate_holder),
+      context_holder_(new gin::ContextHolder(isolate_holder_->isolate())),
+      handle_scope_(isolate_holder_->isolate()),
+      source_map_(new StringSourceMap()) {
+  context_holder_->SetContext(
+      v8::Context::New(isolate_holder->isolate(),
+                       g_v8_extension_configurator.Get().GetConfiguration()));
+  context_.reset(new ScriptContext(context_holder_->context(),
+                                   NULL,  // WebFrame
+                                   NULL,  // Extension
+                                   Feature::UNSPECIFIED_CONTEXT));
+  context_->v8_context()->Enter();
+  assert_natives_ = new AssertNatives(context_.get());
+
+  {
+    scoped_ptr<ModuleSystem> module_system(
+        new ModuleSystem(context_.get(), source_map_.get()));
+    context_->set_module_system(module_system.Pass());
+  }
+  ModuleSystem* module_system = context_->module_system();
+  module_system->RegisterNativeHandler(
+      "assert", scoped_ptr<NativeHandler>(assert_natives_));
+  module_system->RegisterNativeHandler(
+      "logging",
+      scoped_ptr<NativeHandler>(new LoggingNativeHandler(context_.get())));
+  module_system->RegisterNativeHandler(
+      "utils",
+      scoped_ptr<NativeHandler>(new UtilsNativeHandler(context_.get())));
+  module_system->SetExceptionHandlerForTest(
+      scoped_ptr<ModuleSystem::ExceptionHandler>(new FailsOnException));
+}
+
+ModuleSystemTestEnvironment::~ModuleSystemTestEnvironment() {
+  if (context_)
+    context_->v8_context()->Exit();
+}
+
+void ModuleSystemTestEnvironment::RegisterModule(const std::string& name,
+                                                 const std::string& code) {
+  source_map_->RegisterModule(name, code);
+}
+
+void ModuleSystemTestEnvironment::RegisterModule(const std::string& name,
+                                                 int resource_id) {
+  const std::string& code = ResourceBundle::GetSharedInstance()
+                                .GetRawDataResource(resource_id)
+                                .as_string();
+  source_map_->RegisterModule(name, code);
+}
+
+void ModuleSystemTestEnvironment::OverrideNativeHandler(
+    const std::string& name,
+    const std::string& code) {
+  RegisterModule(name, code);
+  context_->module_system()->OverrideNativeHandlerForTest(name);
+}
+
+void ModuleSystemTestEnvironment::RegisterTestFile(
+    const std::string& module_name,
+    const std::string& file_name) {
+  base::FilePath test_js_file_path;
+  ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_js_file_path));
+  test_js_file_path = test_js_file_path.AppendASCII(file_name);
+  std::string test_js;
+  ASSERT_TRUE(base::ReadFileToString(test_js_file_path, &test_js));
+  source_map_->RegisterModule(module_name, test_js);
+}
+
+void ModuleSystemTestEnvironment::ShutdownGin() {
+  context_holder_.reset();
+}
+
+void ModuleSystemTestEnvironment::ShutdownModuleSystem() {
+  context_->v8_context()->Exit();
+  context_.reset();
+}
+
+v8::Handle<v8::Object> ModuleSystemTestEnvironment::CreateGlobal(
+    const std::string& name) {
+  v8::Isolate* isolate = isolate_holder_->isolate();
+  v8::EscapableHandleScope handle_scope(isolate);
+  v8::Local<v8::Object> object = v8::Object::New(isolate);
+  isolate->GetCurrentContext()->Global()->Set(
+      v8::String::NewFromUtf8(isolate, name.c_str()), object);
+  return handle_scope.Escape(object);
+}
+
+ModuleSystemTest::ModuleSystemTest()
+    : isolate_holder_(v8::Isolate::GetCurrent(), NULL),
+      env_(CreateEnvironment()),
+      should_assertions_be_made_(true) {
+}
+
+ModuleSystemTest::~ModuleSystemTest() {
+}
+
+void ModuleSystemTest::TearDown() {
+  // All tests must assert at least once unless otherwise specified.
+  EXPECT_EQ(should_assertions_be_made_,
+            env_->assert_natives()->assertion_made());
+  EXPECT_FALSE(env_->assert_natives()->failed());
+}
+
+scoped_ptr<ModuleSystemTestEnvironment> ModuleSystemTest::CreateEnvironment() {
+  return make_scoped_ptr(new ModuleSystemTestEnvironment(&isolate_holder_));
+}
+
+void ModuleSystemTest::ExpectNoAssertionsMade() {
+  should_assertions_be_made_ = false;
+}
+
+void ModuleSystemTest::RunResolvedPromises() {
+  isolate_holder_.isolate()->RunMicrotasks();
+}
+
+}  // namespace extensions