Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Unified Diff: extensions/renderer/api_test_base.cc

Issue 399363002: Add support for writing unit tests for Mojo-backed apps/extensions APIs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698