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

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: address comments 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..46b53ba7292e0f49395e3fe3bf3156bf1bd86065
--- /dev/null
+++ b/extensions/renderer/api_test_base.cc
@@ -0,0 +1,224 @@
+// 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 <vector>
+
+#include "base/run_loop.h"
+#include "extensions/common/extension_urls.h"
+#include "extensions/renderer/dispatcher.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 "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"
+
+namespace extensions {
+namespace {
+
+// Natives for the implementation of the unit test version of chrome.test. Calls
+// the provided |quit_closure| when either notifyPass or notifyFail is called.
+class TestNatives : public gin::Wrappable<TestNatives> {
+ public:
+ static gin::Handle<TestNatives> Create(v8::Isolate* isolate,
+ const base::Closure& quit_closure) {
+ return gin::CreateHandle(isolate, new TestNatives(quit_closure));
+ }
+
+ 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, quit_closure_);
+ }
+
+ static gin::WrapperInfo kWrapperInfo;
+
+ private:
+ explicit TestNatives(const base::Closure& quit_closure)
+ : quit_closure_(quit_closure) {}
+
+ const base::Closure quit_closure_;
+ 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);
+ const std::vector<std::pair<std::string, int> > resources =
+ Dispatcher::GetJsResources();
+ for (std::vector<std::pair<std::string, int> >::const_iterator resource =
+ resources.begin();
+ resource != resources.end();
+ ++resource) {
+ if (resource->first != "test_delegate")
+ env()->RegisterModule(resource->first, resource->second);
+ }
+ 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_delegate",
+ "test_custom_bindings_unittest_delegate.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 [] };");
+
+ 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());
+}
+
+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::RunLoop run_loop;
+ gin::ModuleRegistry::From(env()->context()->v8_context())->AddBuiltinModule(
+ env()->isolate(),
+ "testNatives",
+ TestNatives::Create(env()->isolate(), run_loop.QuitClosure()).ToV8());
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(&ApiTestBase::RunTestInner,
+ base::Unretained(this),
+ test_name,
+ run_loop.QuitClosure()));
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&ApiTestBase::RunPromisesAgain, base::Unretained(this)));
+ run_loop.Run();
+}
+
+void ApiTestBase::RunTestInner(const std::string& test_name,
+ const base::Closure& quit_closure) {
+ 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()) {
+ base::MessageLoop::current()->PostTask(FROM_HERE, quit_closure);
+ 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