Chromium Code Reviews| Index: extensions/renderer/api_test_base.cc |
| diff --git a/extensions/renderer/api_test_base.cc b/extensions/renderer/api_test_base.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0b82d2eb3852d1542413d7c2a434f605edd1f508 |
| --- /dev/null |
| +++ b/extensions/renderer/api_test_base.cc |
| @@ -0,0 +1,223 @@ |
| +// 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/api_test_base.h" |
| + |
| +#include "base/run_loop.h" |
| +#include "extensions/common/extension_urls.h" |
| +#include "extensions/renderer/logging_native_handler.h" |
| +#include "extensions/renderer/send_request_natives.h" |
| +#include "extensions/renderer/utils_native_handler.h" |
| +#include "gin/converter.h" |
| +#include "gin/dictionary.h" |
| +#include "grit/content_resources.h" |
| +#include "grit/extensions_renderer_resources.h" |
| +#include "mojo/bindings/js/core.h" |
| +#include "mojo/bindings/js/handle.h" |
| +#include "mojo/bindings/js/support.h" |
| +#include "mojo/public/cpp/bindings/interface_request.h" |
| +#include "mojo/public/cpp/system/core.h" |
| +#include "mojo/public/js/bindings/constants.h" |
| + |
| +namespace extensions { |
| +namespace { |
| + |
| +class TestNatives : public gin::Wrappable<TestNatives> { |
| + public: |
| + static gin::Handle<TestNatives> Create(v8::Isolate* isolate, |
| + base::RunLoop* run_loop) { |
| + return gin::CreateHandle(isolate, new TestNatives(run_loop)); |
| + } |
| + |
| + virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder( |
| + v8::Isolate* isolate) OVERRIDE { |
| + return Wrappable<TestNatives>::GetObjectTemplateBuilder(isolate) |
| + .SetMethod("Log", &TestNatives::Log) |
| + .SetMethod("NotifyPass", &TestNatives::NotifyPass) |
| + .SetMethod("NotifyFail", &TestNatives::NotifyFail); |
| + } |
| + |
| + void Log(const std::string& value) { logs_ += value + "\n"; } |
| + void NotifyPass() { FinishTesting(); } |
| + |
| + void NotifyFail(const std::string& message) { |
| + FinishTesting(); |
| + FAIL() << logs_ << message; |
| + } |
| + |
| + void FinishTesting() { |
| + base::MessageLoop::current()->PostTask(FROM_HERE, run_loop_->QuitClosure()); |
|
not at google - send to devlin
2014/07/18 15:09:13
do you mean to also pump the message loop here? ho
Sam McNally
2014/07/21 03:56:27
The test functions and their callbacks run on the
|
| + } |
| + |
| + static gin::WrapperInfo kWrapperInfo; |
| + |
| + private: |
| + explicit TestNatives(base::RunLoop* run_loop) : run_loop_(run_loop) {} |
| + |
| + base::RunLoop* run_loop_; |
| + std::string logs_; |
| +}; |
| + |
| +gin::WrapperInfo TestNatives::kWrapperInfo = {gin::kEmbedderNativeGin}; |
| + |
| +} // namespace |
| + |
| +gin::WrapperInfo TestServiceProvider::kWrapperInfo = {gin::kEmbedderNativeGin}; |
| + |
| +gin::Handle<TestServiceProvider> TestServiceProvider::Create( |
| + v8::Isolate* isolate) { |
| + return gin::CreateHandle(isolate, new TestServiceProvider()); |
| +} |
| + |
| +TestServiceProvider::~TestServiceProvider() { |
| +} |
| + |
| +gin::ObjectTemplateBuilder TestServiceProvider::GetObjectTemplateBuilder( |
| + v8::Isolate* isolate) { |
| + return Wrappable<TestServiceProvider>::GetObjectTemplateBuilder(isolate) |
| + .SetMethod("connectToService", &TestServiceProvider::ConnectToService); |
| +} |
| + |
| +mojo::Handle TestServiceProvider::ConnectToService( |
| + const std::string& service_name) { |
| + EXPECT_EQ(1u, service_factories_.count(service_name)) |
| + << "Unregistered service " << service_name << " requested."; |
| + mojo::MessagePipe pipe; |
| + std::map<std::string, |
| + base::Callback<void(mojo::ScopedMessagePipeHandle)> >::iterator it = |
| + service_factories_.find(service_name); |
| + if (it != service_factories_.end()) |
| + it->second.Run(pipe.handle0.Pass()); |
| + return pipe.handle1.release(); |
| +} |
| + |
| +TestServiceProvider::TestServiceProvider() { |
| +} |
| + |
| +ApiTestBase::ApiTestBase() { |
| +} |
| +ApiTestBase::~ApiTestBase() { |
| +} |
| + |
| +void ApiTestBase::SetUp() { |
| + ModuleSystemTest::SetUp(); |
| + service_provider_ = TestServiceProvider::Create(env()->isolate()); |
| + InitializeEnvironment(); |
| + RegisterModules(); |
| +} |
| + |
| +void ApiTestBase::RegisterModules() { |
| + v8_schema_registry_.reset(new V8SchemaRegistry); |
| + env()->RegisterModule("json_schema", IDR_JSON_SCHEMA_JS); |
|
not at google - send to devlin
2014/07/18 15:09:13
shame to need to do all of this, since it means th
Sam McNally
2014/07/21 03:56:27
Done.
|
| + env()->RegisterModule("lastError", IDR_LAST_ERROR_JS); |
| + env()->RegisterModule(kEventBindings, IDR_EVENT_BINDINGS_JS); |
| + env()->RegisterModule("schemaUtils", IDR_SCHEMA_UTILS_JS); |
| + env()->RegisterModule("sendRequest", IDR_SEND_REQUEST_JS); |
| + env()->RegisterModule("uncaught_exception_handler", |
| + IDR_UNCAUGHT_EXCEPTION_HANDLER_JS); |
| + env()->RegisterModule("unload_event", IDR_UNLOAD_EVENT_JS); |
| + env()->RegisterModule("utils", IDR_UTILS_JS); |
| + env()->RegisterModule("binding", IDR_BINDING_JS); |
| + env()->module_system()->RegisterNativeHandler( |
| + "logging", |
| + scoped_ptr<NativeHandler>(new LoggingNativeHandler(env()->context()))); |
| + env()->module_system()->RegisterNativeHandler( |
| + "schema_registry", v8_schema_registry_->AsNativeHandler()); |
| + env()->module_system()->RegisterNativeHandler( |
| + "utils", |
| + scoped_ptr<NativeHandler>(new UtilsNativeHandler(env()->context()))); |
| + env()->module_system()->RegisterNativeHandler( |
| + "sendRequest", |
| + scoped_ptr<NativeHandler>( |
| + new SendRequestNatives(NULL, env()->context()))); |
| + env()->RegisterTestFile("test", "test_unittest_custom_bindings.js"); |
| + |
| + env()->OverrideNativeHandler( |
| + "v8_context", |
| + "exports.GetAvailability = function() { return {is_available: true}; };"); |
| + env()->OverrideNativeHandler("activityLogger", |
| + "exports.LogAPICall = function() {};"); |
| + env()->OverrideNativeHandler( |
| + "process", |
| + "exports.GetContextType = function() { return 'BLESSED_EXTENSION'; };" |
| + "exports.GetExtensionId = function() { return 'id'; };" |
| + "exports.GetManifestVersion = function() { return 2 };"); |
| + env()->OverrideNativeHandler( |
| + "event_natives", |
| + "exports.AttachEvent = function() {};" |
| + "exports.DetachEvent = function() {};" |
| + "exports.AttachFilteredEvent = function() {};" |
| + "exports.AttachFilteredEvent = function() {};" |
| + "exports.MatchAgainstEventFilter = function() { return [] };"); |
| + |
| + env()->RegisterModule(mojo::kCodecModuleName, IDR_MOJO_CODEC_JS); |
| + env()->RegisterModule(mojo::kConnectionModuleName, IDR_MOJO_CONNECTION_JS); |
| + env()->RegisterModule(mojo::kConnectorModuleName, IDR_MOJO_CONNECTOR_JS); |
| + env()->RegisterModule(mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS); |
| + env()->RegisterModule(mojo::kUnicodeModuleName, IDR_MOJO_UNICODE_JS); |
| + gin::ModuleRegistry::From(env()->context()->v8_context()) |
| + ->AddBuiltinModule(env()->isolate(), |
| + mojo::js::Core::kModuleName, |
| + mojo::js::Core::GetModule(env()->isolate())); |
| + gin::ModuleRegistry::From(env()->context()->v8_context()) |
| + ->AddBuiltinModule(env()->isolate(), |
| + mojo::js::Support::kModuleName, |
| + mojo::js::Support::GetModule(env()->isolate())); |
| + gin::ModuleRegistry::From(env()->context()->v8_context()) |
| + ->AddBuiltinModule(env()->isolate(), |
| + "content/public/renderer/service_provider", |
| + service_provider_.ToV8()); |
| + gin::ModuleRegistry::From(env()->context()->v8_context())->AddBuiltinModule( |
| + env()->isolate(), |
| + "testNatives", |
| + TestNatives::Create(env()->isolate(), &run_loop_).ToV8()); |
| +} |
| + |
| +void ApiTestBase::InitializeEnvironment() { |
| + gin::Dictionary global(env()->isolate(), |
| + env()->context()->v8_context()->Global()); |
| + gin::Dictionary navigator(gin::Dictionary::CreateEmpty(env()->isolate())); |
| + navigator.Set("appVersion", base::StringPiece("")); |
| + global.Set("navigator", navigator); |
| + gin::Dictionary chrome(gin::Dictionary::CreateEmpty(env()->isolate())); |
| + global.Set("chrome", chrome); |
| + gin::Dictionary extension(gin::Dictionary::CreateEmpty(env()->isolate())); |
| + chrome.Set("extension", extension); |
| + gin::Dictionary runtime(gin::Dictionary::CreateEmpty(env()->isolate())); |
| + chrome.Set("runtime", runtime); |
| +} |
| + |
| +void ApiTestBase::RunTest(const std::string& file_name, |
| + const std::string& test_name) { |
| + env()->RegisterTestFile("testBody", file_name); |
| + ExpectNoAssertionsMade(); |
| + base::MessageLoop::current()->PostTask( |
| + FROM_HERE, |
| + base::Bind( |
| + &ApiTestBase::RunTestInner, base::Unretained(this), test_name)); |
| + base::MessageLoop::current()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&ApiTestBase::RunPromisesAgain, base::Unretained(this))); |
| + run_loop_.Run(); |
| +} |
| + |
| +void ApiTestBase::RunTestInner(const std::string& test_name) { |
| + v8::HandleScope scope(env()->isolate()); |
| + ModuleSystem::NativesEnabledScope natives_enabled(env()->module_system()); |
| + v8::Handle<v8::Value> result = |
| + env()->module_system()->CallModuleMethod("testBody", test_name); |
| + if (!result->IsTrue()) { |
| + run_loop_.Quit(); |
| + FAIL() << "Failed to run test \"" << test_name << "\""; |
| + } |
| +} |
| + |
| +void ApiTestBase::RunPromisesAgain() { |
| + RunResolvedPromises(); |
| + base::MessageLoop::current()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&ApiTestBase::RunPromisesAgain, base::Unretained(this))); |
| +} |
| + |
| +} // namespace extensions |