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

Side by Side Diff: third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp

Issue 2822453003: Wrap large IndexedDB values into Blobs before writing to LevelDB. (Closed)
Patch Set: Fixed Windows compilation. Created 3 years, 6 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 15 matching lines...) Expand all
26 #include "modules/indexeddb/IDBRequest.h" 26 #include "modules/indexeddb/IDBRequest.h"
27 27
28 #include <memory> 28 #include <memory>
29 29
30 #include "bindings/core/v8/V8BindingForCore.h" 30 #include "bindings/core/v8/V8BindingForCore.h"
31 #include "bindings/core/v8/V8BindingForTesting.h" 31 #include "bindings/core/v8/V8BindingForTesting.h"
32 #include "core/dom/DOMException.h" 32 #include "core/dom/DOMException.h"
33 #include "core/dom/ExceptionCode.h" 33 #include "core/dom/ExceptionCode.h"
34 #include "core/dom/ExecutionContext.h" 34 #include "core/dom/ExecutionContext.h"
35 #include "core/testing/NullExecutionContext.h" 35 #include "core/testing/NullExecutionContext.h"
36 #include "modules/indexeddb/IDBDatabase.h"
36 #include "modules/indexeddb/IDBDatabaseCallbacks.h" 37 #include "modules/indexeddb/IDBDatabaseCallbacks.h"
37 #include "modules/indexeddb/IDBKey.h" 38 #include "modules/indexeddb/IDBKey.h"
38 #include "modules/indexeddb/IDBOpenDBRequest.h" 39 #include "modules/indexeddb/IDBOpenDBRequest.h"
40 #include "modules/indexeddb/IDBTransaction.h"
39 #include "modules/indexeddb/IDBValue.h" 41 #include "modules/indexeddb/IDBValue.h"
42 #include "modules/indexeddb/IDBValueWrapping.h"
40 #include "modules/indexeddb/MockWebIDBDatabase.h" 43 #include "modules/indexeddb/MockWebIDBDatabase.h"
41 #include "platform/SharedBuffer.h" 44 #include "platform/SharedBuffer.h"
42 #include "platform/bindings/ScriptState.h" 45 #include "platform/bindings/ScriptState.h"
43 #include "platform/wtf/PassRefPtr.h" 46 #include "platform/wtf/PassRefPtr.h"
44 #include "platform/wtf/Vector.h" 47 #include "platform/wtf/Vector.h"
45 #include "platform/wtf/dtoa/utils.h" 48 #include "platform/wtf/dtoa/utils.h"
49 #include "public/platform/Platform.h"
50 #include "public/platform/WebURLLoaderMockFactory.h"
51 #include "public/platform/WebURLResponse.h"
46 #include "public/platform/modules/indexeddb/WebIDBCallbacks.h" 52 #include "public/platform/modules/indexeddb/WebIDBCallbacks.h"
47 #include "testing/gtest/include/gtest/gtest.h" 53 #include "testing/gtest/include/gtest/gtest.h"
48 #include "v8/include/v8.h" 54 #include "v8/include/v8.h"
49 55
50 namespace blink { 56 namespace blink {
51 namespace { 57 namespace {
52 58
53 TEST(IDBRequestTest, EventsAfterStopping) { 59 class IDBRequestTest : public ::testing::Test {
60 protected:
61 void SetUp() override {
62 url_loader_mock_factory_ = Platform::Current()->GetURLLoaderMockFactory();
63 WebURLResponse response;
64 response.SetURL(KURL(KURL(), "blob:"));
65 url_loader_mock_factory_->RegisterURLProtocol(WebString("blob"), response,
66 "");
67 }
68
69 void TearDown() override {
70 url_loader_mock_factory_->UnregisterAllURLsAndClearMemoryCache();
71 }
72
73 void BuildTransaction(V8TestingScope& scope,
74 std::unique_ptr<MockWebIDBDatabase> backend) {
75 db_ =
76 IDBDatabase::Create(scope.GetExecutionContext(), std::move(backend),
77 IDBDatabaseCallbacks::Create(), scope.GetIsolate());
78
79 HashSet<String> transaction_scope = {"store"};
80 transaction_ = IDBTransaction::CreateNonVersionChange(
81 scope.GetScriptState(), kTransactionId, transaction_scope,
82 kWebIDBTransactionModeReadOnly, db_.Get());
83 }
84
85 WebURLLoaderMockFactory* url_loader_mock_factory_;
86 Persistent<IDBDatabase> db_;
87 Persistent<IDBTransaction> transaction_;
88
89 static constexpr int64_t kTransactionId = 1234;
90 };
91
92 // The created value is an array of true. If create_wrapped_value is true, the
93 // IDBValue's byte array will be wrapped in a Blob, otherwise it will not be.
94 RefPtr<IDBValue> CreateIDBValue(v8::Isolate* isolate,
95 bool create_wrapped_value) {
96 size_t element_count = create_wrapped_value ? 16 : 2;
97 v8::Local<v8::Array> v8_array = v8::Array::New(isolate, element_count);
98 for (size_t i = 0; i < element_count; ++i)
99 v8_array->Set(i, v8::True(isolate));
100
101 NonThrowableExceptionState non_throwable_exception_state;
102 IDBValueWrapper wrapper(isolate, v8_array,
103 SerializedScriptValue::SerializeOptions::kSerialize,
104 non_throwable_exception_state);
105 wrapper.WrapIfBiggerThan(create_wrapped_value ? 0 : 1024 * element_count);
106
107 std::unique_ptr<Vector<RefPtr<BlobDataHandle>>> blob_data_handles =
108 WTF::MakeUnique<Vector<RefPtr<BlobDataHandle>>>();
109 wrapper.ExtractBlobDataHandles(blob_data_handles.get());
110 Vector<WebBlobInfo>& blob_infos = wrapper.WrappedBlobInfo();
111 RefPtr<SharedBuffer> wrapped_marker_buffer = wrapper.ExtractWireBytes();
112
113 RefPtr<IDBValue> idb_value =
114 IDBValue::Create(wrapped_marker_buffer, std::move(blob_data_handles),
115 WTF::MakeUnique<Vector<WebBlobInfo>>(blob_infos));
116
117 DCHECK_EQ(create_wrapped_value,
118 IDBValueUnwrapper::IsWrapped(idb_value.Get()));
119 return idb_value;
120 }
121
122 void EnsureIDBCallbacksDontThrow(IDBRequest* request,
123 ExceptionState& exception_state) {
124 ASSERT_TRUE(request->transaction());
125
126 request->HandleResponse(
127 DOMException::Create(kAbortError, "Description goes here."));
128 request->HandleResponse(nullptr, IDBKey::CreateInvalid(),
129 IDBKey::CreateInvalid(), IDBValue::Create());
130 request->HandleResponse(IDBKey::CreateInvalid());
131 request->HandleResponse(IDBValue::Create());
132 request->HandleResponse(static_cast<int64_t>(0));
133 request->HandleResponse();
134 request->HandleResponse(IDBKey::CreateInvalid(), IDBKey::CreateInvalid(),
135 IDBValue::Create());
136 request->EnqueueResponse(Vector<String>());
137
138 EXPECT_TRUE(!exception_state.HadException());
139 }
140
141 TEST_F(IDBRequestTest, EventsAfterEarlyDeathStop) {
142 V8TestingScope scope;
143 std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
144 EXPECT_CALL(*backend, Close()).Times(1);
145 BuildTransaction(scope, std::move(backend));
146
147 ASSERT_TRUE(!scope.GetExceptionState().HadException());
148 ASSERT_TRUE(transaction_);
149
150 IDBRequest* request = IDBRequest::Create(
151 scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
152 EXPECT_EQ(request->readyState(), "pending");
153 ASSERT_TRUE(!scope.GetExceptionState().HadException());
154 ASSERT_TRUE(request->transaction());
155 scope.GetExecutionContext()->NotifyContextDestroyed();
156
157 EnsureIDBCallbacksDontThrow(request, scope.GetExceptionState());
158 }
159
160 TEST_F(IDBRequestTest, EventsAfterDoneStop) {
161 V8TestingScope scope;
162 std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
163 EXPECT_CALL(*backend, Close()).Times(1);
164 BuildTransaction(scope, std::move(backend));
165
166 ASSERT_TRUE(!scope.GetExceptionState().HadException());
167 ASSERT_TRUE(transaction_);
168
169 IDBRequest* request = IDBRequest::Create(
170 scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
171 ASSERT_TRUE(!scope.GetExceptionState().HadException());
172 ASSERT_TRUE(request->transaction());
173 request->HandleResponse(CreateIDBValue(scope.GetIsolate(), false));
174 scope.GetExecutionContext()->NotifyContextDestroyed();
175
176 EnsureIDBCallbacksDontThrow(request, scope.GetExceptionState());
177 }
178
179 TEST_F(IDBRequestTest, EventsAfterEarlyDeathStopWithQueuedResult) {
180 V8TestingScope scope;
181 std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
182 EXPECT_CALL(*backend, Close()).Times(1);
183 BuildTransaction(scope, std::move(backend));
184
185 ASSERT_TRUE(!scope.GetExceptionState().HadException());
186 ASSERT_TRUE(transaction_);
187
188 IDBRequest* request = IDBRequest::Create(
189 scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
190 EXPECT_EQ(request->readyState(), "pending");
191 ASSERT_TRUE(!scope.GetExceptionState().HadException());
192 ASSERT_TRUE(request->transaction());
193 request->HandleResponse(CreateIDBValue(scope.GetIsolate(), true));
194 scope.GetExecutionContext()->NotifyContextDestroyed();
195
196 EnsureIDBCallbacksDontThrow(request, scope.GetExceptionState());
197 url_loader_mock_factory_->ServeAsynchronousRequests();
198 EnsureIDBCallbacksDontThrow(request, scope.GetExceptionState());
199 }
200
201 TEST_F(IDBRequestTest, EventsAfterEarlyDeathStopWithTwoQueuedResults) {
202 V8TestingScope scope;
203 std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
204 EXPECT_CALL(*backend, Close()).Times(1);
205 BuildTransaction(scope, std::move(backend));
206
207 ASSERT_TRUE(!scope.GetExceptionState().HadException());
208 ASSERT_TRUE(transaction_);
209
210 IDBRequest* request1 = IDBRequest::Create(
211 scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
212 IDBRequest* request2 = IDBRequest::Create(
213 scope.GetScriptState(), IDBAny::CreateUndefined(), transaction_.Get());
214 EXPECT_EQ(request1->readyState(), "pending");
215 EXPECT_EQ(request2->readyState(), "pending");
216 ASSERT_TRUE(!scope.GetExceptionState().HadException());
217 ASSERT_TRUE(request1->transaction());
218 ASSERT_TRUE(request2->transaction());
219 request1->HandleResponse(CreateIDBValue(scope.GetIsolate(), true));
220 request2->HandleResponse(CreateIDBValue(scope.GetIsolate(), true));
221 scope.GetExecutionContext()->NotifyContextDestroyed();
222
223 EnsureIDBCallbacksDontThrow(request1, scope.GetExceptionState());
224 EnsureIDBCallbacksDontThrow(request2, scope.GetExceptionState());
225 url_loader_mock_factory_->ServeAsynchronousRequests();
226 EnsureIDBCallbacksDontThrow(request1, scope.GetExceptionState());
227 EnsureIDBCallbacksDontThrow(request2, scope.GetExceptionState());
228 }
229
230 TEST_F(IDBRequestTest, AbortErrorAfterAbort) {
54 V8TestingScope scope; 231 V8TestingScope scope;
55 IDBTransaction* transaction = nullptr; 232 IDBTransaction* transaction = nullptr;
56 IDBRequest* request = IDBRequest::Create( 233 IDBRequest* request = IDBRequest::Create(
57 scope.GetScriptState(), IDBAny::CreateUndefined(), transaction);
58 EXPECT_EQ(request->readyState(), "pending");
59 scope.GetExecutionContext()->NotifyContextDestroyed();
60
61 // Ensure none of the following raise assertions in stopped state:
62 request->EnqueueResponse(
63 DOMException::Create(kAbortError, "Description goes here."));
64 request->EnqueueResponse(Vector<String>());
65 request->EnqueueResponse(nullptr, IDBKey::CreateInvalid(),
66 IDBKey::CreateInvalid(), IDBValue::Create());
67 request->EnqueueResponse(IDBKey::CreateInvalid());
68 request->EnqueueResponse(IDBValue::Create());
69 request->EnqueueResponse(static_cast<int64_t>(0));
70 request->EnqueueResponse();
71 request->EnqueueResponse(IDBKey::CreateInvalid(), IDBKey::CreateInvalid(),
72 IDBValue::Create());
73 }
74
75 TEST(IDBRequestTest, AbortErrorAfterAbort) {
76 V8TestingScope scope;
77 IDBTransaction* transaction = nullptr;
78 IDBRequest* request = IDBRequest::Create(
79 scope.GetScriptState(), IDBAny::CreateUndefined(), transaction); 234 scope.GetScriptState(), IDBAny::CreateUndefined(), transaction);
80 EXPECT_EQ(request->readyState(), "pending"); 235 EXPECT_EQ(request->readyState(), "pending");
81 236
82 // Simulate the IDBTransaction having received OnAbort from back end and 237 // Simulate the IDBTransaction having received OnAbort from back end and
83 // aborting the request: 238 // aborting the request:
84 request->Abort(); 239 request->Abort();
85 240
86 // Now simulate the back end having fired an abort error at the request to 241 // Now simulate the back end having fired an abort error at the request to
87 // clear up any intermediaries. Ensure an assertion is not raised. 242 // clear up any intermediaries. Ensure an assertion is not raised.
88 request->EnqueueResponse( 243 request->HandleResponse(
89 DOMException::Create(kAbortError, "Description goes here.")); 244 DOMException::Create(kAbortError, "Description goes here."));
90 245
91 // Stop the request lest it be GCed and its destructor 246 // Stop the request lest it be GCed and its destructor
92 // finds the object in a pending state (and asserts.) 247 // finds the object in a pending state (and asserts.)
93 scope.GetExecutionContext()->NotifyContextDestroyed(); 248 scope.GetExecutionContext()->NotifyContextDestroyed();
94 } 249 }
95 250
96 TEST(IDBRequestTest, ConnectionsAfterStopping) { 251 TEST_F(IDBRequestTest, ConnectionsAfterStopping) {
97 V8TestingScope scope; 252 V8TestingScope scope;
98 const int64_t kTransactionId = 1234; 253 const int64_t kTransactionId = 1234;
99 const int64_t kVersion = 1; 254 const int64_t kVersion = 1;
100 const int64_t kOldVersion = 0; 255 const int64_t kOldVersion = 0;
101 const WebIDBMetadata metadata; 256 const WebIDBMetadata metadata;
102 Persistent<IDBDatabaseCallbacks> callbacks = IDBDatabaseCallbacks::Create(); 257 Persistent<IDBDatabaseCallbacks> callbacks = IDBDatabaseCallbacks::Create();
103 258
104 { 259 {
105 std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create(); 260 std::unique_ptr<MockWebIDBDatabase> backend = MockWebIDBDatabase::Create();
106 EXPECT_CALL(*backend, Close()).Times(1); 261 EXPECT_CALL(*backend, Close()).Times(1);
(...skipping 15 matching lines...) Expand all
122 EXPECT_EQ(request->readyState(), "pending"); 277 EXPECT_EQ(request->readyState(), "pending");
123 std::unique_ptr<WebIDBCallbacks> callbacks = request->CreateWebCallbacks(); 278 std::unique_ptr<WebIDBCallbacks> callbacks = request->CreateWebCallbacks();
124 279
125 scope.GetExecutionContext()->NotifyContextDestroyed(); 280 scope.GetExecutionContext()->NotifyContextDestroyed();
126 callbacks->OnSuccess(backend.release(), metadata); 281 callbacks->OnSuccess(backend.release(), metadata);
127 } 282 }
128 } 283 }
129 284
130 } // namespace 285 } // namespace
131 } // namespace blink 286 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698