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

Unified Diff: extensions/renderer/api_last_error_unittest.cc

Issue 2657613005: [Extensions Bindings] Add chrome.runtime.lastError support (Closed)
Patch Set: . Created 3 years, 10 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
« no previous file with comments | « extensions/renderer/api_last_error.cc ('k') | extensions/renderer/api_request_handler.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: extensions/renderer/api_last_error_unittest.cc
diff --git a/extensions/renderer/api_last_error_unittest.cc b/extensions/renderer/api_last_error_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fd4a964362fa66bd20f41df01cfcb5844896a76c
--- /dev/null
+++ b/extensions/renderer/api_last_error_unittest.cc
@@ -0,0 +1,167 @@
+// Copyright 2017 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_last_error.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "extensions/renderer/api_binding_test.h"
+#include "extensions/renderer/api_binding_test_util.h"
+#include "gin/converter.h"
+#include "gin/public/context_holder.h"
+
+namespace extensions {
+
+namespace {
+
+std::string GetLastError(v8::Local<v8::Object> parent,
+ v8::Local<v8::Context> context) {
+ v8::Local<v8::Value> last_error =
+ GetPropertyFromObject(parent, context, "lastError");
+ if (last_error.IsEmpty() || !last_error->IsObject())
+ return V8ToString(last_error, context);
+ v8::Local<v8::Value> message =
+ GetPropertyFromObject(last_error.As<v8::Object>(), context, "message");
+ return V8ToString(message, context);
+}
+
+using ParentList =
+ std::vector<std::pair<v8::Local<v8::Context>, v8::Local<v8::Object>>>;
+v8::Local<v8::Object> GetParent(const ParentList& parents,
+ v8::Local<v8::Context> context) {
+ // This would be simpler with a map<context, object>, but Local<> doesn't
+ // define an operator<.
+ for (const auto& parent : parents) {
+ if (parent.first == context)
+ return parent.second;
+ }
+ return v8::Local<v8::Object>();
+}
+
+} // namespace
+
+using APILastErrorTest = APIBindingTest;
+
+// Test basic functionality of the lastError object.
+TEST_F(APILastErrorTest, TestLastError) {
+ v8::HandleScope handle_scope(isolate());
+ v8::Local<v8::Context> context = ContextLocal();
+ v8::Local<v8::Object> parent_object = v8::Object::New(isolate());
+
+ ParentList parents = {{context, parent_object}};
+ APILastError last_error(base::Bind(&GetParent, parents));
+
+ EXPECT_EQ("undefined", GetLastError(parent_object, context));
+ // Check that the key isn't present on the object (as opposed to simply being
+ // undefined).
+ EXPECT_FALSE(
+ parent_object->Has(context, gin::StringToV8(isolate(), "lastError"))
+ .ToChecked());
+
+ last_error.SetError(context, "Some last error");
+ EXPECT_EQ("\"Some last error\"", GetLastError(parent_object, context));
+
+ last_error.ClearError(context, false);
+ EXPECT_EQ("undefined", GetLastError(parent_object, context));
+ EXPECT_FALSE(
+ parent_object->Has(context, gin::StringToV8(isolate(), "lastError"))
+ .ToChecked());
+}
+
+// Test throwing an error if the last error wasn't checked.
+TEST_F(APILastErrorTest, ReportIfUnchecked) {
+ v8::HandleScope handle_scope(isolate());
+ v8::Local<v8::Context> context = ContextLocal();
+ v8::Local<v8::Object> parent_object = v8::Object::New(isolate());
+
+ ParentList parents = {{context, parent_object}};
+ APILastError last_error(base::Bind(&GetParent, parents));
+
+ {
+ v8::TryCatch try_catch(isolate());
+ last_error.SetError(context, "foo");
+ // GetLastError() will count as accessing the error property, so we
+ // shouldn't throw an exception.
+ EXPECT_EQ("\"foo\"", GetLastError(parent_object, context));
+ last_error.ClearError(context, true);
+ EXPECT_FALSE(try_catch.HasCaught());
+ }
+
+ {
+ v8::TryCatch try_catch(isolate());
+ // This time, we should throw an exception.
+ last_error.SetError(context, "A last error");
+ last_error.ClearError(context, true);
+ ASSERT_TRUE(try_catch.HasCaught());
+ EXPECT_EQ("Uncaught Error: A last error",
+ gin::V8ToString(try_catch.Message()->Get()));
+ }
+}
+
+// Test behavior when something else sets a lastError property on the parent
+// object.
+TEST_F(APILastErrorTest, NonLastErrorObject) {
+ v8::HandleScope handle_scope(isolate());
+ v8::Local<v8::Context> context = ContextLocal();
+ v8::Local<v8::Object> parent_object = v8::Object::New(isolate());
+
+ ParentList parents = {{context, parent_object}};
+ APILastError last_error(base::Bind(&GetParent, parents));
+
+ auto checked_set = [context](v8::Local<v8::Object> object,
+ base::StringPiece key,
+ v8::Local<v8::Value> value) {
+ v8::Maybe<bool> success = object->Set(
+ context, gin::StringToSymbol(context->GetIsolate(), key), value);
+ ASSERT_TRUE(success.IsJust());
+ ASSERT_TRUE(success.FromJust());
+ };
+
+ // Set a "fake" lastError property on the parent.
+ v8::Local<v8::Object> fake_last_error = v8::Object::New(isolate());
+ checked_set(fake_last_error, "message",
+ gin::StringToV8(isolate(), "fake error"));
+ checked_set(parent_object, "lastError", fake_last_error);
+
+ EXPECT_EQ("\"fake error\"", GetLastError(parent_object, context));
+
+ // The bindings shouldn't mangle an existing property (or maybe we should -
+ // see the TODO in api_last_error.cc).
+ last_error.SetError(context, "Real last error");
+ EXPECT_EQ("\"fake error\"", GetLastError(parent_object, context));
+ last_error.ClearError(context, false);
+ EXPECT_EQ("\"fake error\"", GetLastError(parent_object, context));
+}
+
+// Test lastError in multiple different contexts.
+TEST_F(APILastErrorTest, MultipleContexts) {
+ v8::HandleScope handle_scope(isolate());
+ v8::Local<v8::Context> context_a = ContextLocal();
+ v8::Local<v8::Context> context_b = v8::Context::New(isolate());
+ gin::ContextHolder holder_b(isolate());
+ holder_b.SetContext(context_b);
+
+ v8::Local<v8::Object> parent_a = v8::Object::New(isolate());
+ v8::Local<v8::Object> parent_b = v8::Object::New(isolate());
+ ParentList parents = {{context_a, parent_a}, {context_b, parent_b}};
+ APILastError last_error(base::Bind(&GetParent, parents));
+
+ last_error.SetError(context_a, "Last error a");
+ EXPECT_EQ("\"Last error a\"", GetLastError(parent_a, context_a));
+ EXPECT_EQ("undefined", GetLastError(parent_b, context_b));
+
+ last_error.SetError(context_b, "Last error b");
+ EXPECT_EQ("\"Last error a\"", GetLastError(parent_a, context_a));
+ EXPECT_EQ("\"Last error b\"", GetLastError(parent_b, context_b));
+
+ last_error.ClearError(context_b, false);
+ EXPECT_EQ("\"Last error a\"", GetLastError(parent_a, context_a));
+ EXPECT_EQ("undefined", GetLastError(parent_b, context_b));
+
+ last_error.ClearError(context_a, false);
+ EXPECT_EQ("undefined", GetLastError(parent_a, context_a));
+ EXPECT_EQ("undefined", GetLastError(parent_b, context_b));
+}
+
+} // namespace extensions
« no previous file with comments | « extensions/renderer/api_last_error.cc ('k') | extensions/renderer/api_request_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698