Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / content / child / indexed_db / indexed_db_dispatcher_unittest.cc
blob7e146e7b00b46bf37464f241f493bd99346f3510
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/memory/scoped_ptr.h"
6 #include "base/single_thread_task_runner.h"
7 #include "base/thread_task_runner_handle.h"
8 #include "base/values.h"
9 #include "content/child/indexed_db/indexed_db_dispatcher.h"
10 #include "content/child/indexed_db/webidbcursor_impl.h"
11 #include "content/child/thread_safe_sender.h"
12 #include "content/common/indexed_db/indexed_db_key.h"
13 #include "content/common/indexed_db/indexed_db_key_range.h"
14 #include "content/common/indexed_db/indexed_db_messages.h"
15 #include "ipc/ipc_sync_message_filter.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "third_party/WebKit/public/platform/WebBlobInfo.h"
18 #include "third_party/WebKit/public/platform/WebData.h"
19 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBCallbacks.h"
20 #include "third_party/WebKit/public/web/WebHeap.h"
22 using blink::WebBlobInfo;
23 using blink::WebData;
24 using blink::WebIDBCallbacks;
25 using blink::WebIDBCursor;
26 using blink::WebIDBDatabase;
27 using blink::WebIDBDatabaseError;
28 using blink::WebIDBKey;
29 using blink::WebIDBValue;
30 using blink::WebVector;
32 namespace content {
33 namespace {
35 class MockCallbacks : public WebIDBCallbacks {
36 public:
37 MockCallbacks() : error_seen_(false) {}
39 virtual void onError(const WebIDBDatabaseError&) { error_seen_ = true; }
41 bool error_seen() const { return error_seen_; }
43 private:
44 bool error_seen_;
46 DISALLOW_COPY_AND_ASSIGN(MockCallbacks);
49 class MockDispatcher : public IndexedDBDispatcher {
50 public:
51 explicit MockDispatcher(ThreadSafeSender* sender)
52 : IndexedDBDispatcher(sender) {}
54 bool Send(IPC::Message* msg) override {
55 delete msg;
56 return true;
59 private:
60 DISALLOW_COPY_AND_ASSIGN(MockDispatcher);
63 } // namespace
65 class IndexedDBDispatcherTest : public testing::Test {
66 public:
67 IndexedDBDispatcherTest()
68 : task_runner_(base::ThreadTaskRunnerHandle::Get()),
69 sync_message_filter_(new IPC::SyncMessageFilter(NULL)),
70 thread_safe_sender_(new ThreadSafeSender(task_runner_.get(),
71 sync_message_filter_.get())) {}
73 void TearDown() override { blink::WebHeap::collectAllGarbageForTesting(); }
75 protected:
76 base::MessageLoop message_loop_;
77 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
78 scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
79 scoped_refptr<ThreadSafeSender> thread_safe_sender_;
81 private:
82 DISALLOW_COPY_AND_ASSIGN(IndexedDBDispatcherTest);
85 TEST_F(IndexedDBDispatcherTest, ValueSizeTest) {
86 const std::vector<char> data(kMaxIDBValueSizeInBytes + 1);
87 const WebData value(&data.front(), data.size());
88 const WebVector<WebBlobInfo> web_blob_info;
89 const int32 ipc_dummy_id = -1;
90 const int64 transaction_id = 1;
91 const int64 object_store_id = 2;
93 MockCallbacks callbacks;
94 IndexedDBDispatcher dispatcher(thread_safe_sender_.get());
95 IndexedDBKey key(0, blink::WebIDBKeyTypeNumber);
96 dispatcher.RequestIDBDatabasePut(ipc_dummy_id,
97 transaction_id,
98 object_store_id,
99 value,
100 web_blob_info,
101 key,
102 blink::WebIDBPutModeAddOrUpdate,
103 &callbacks,
104 WebVector<long long>(),
105 WebVector<WebVector<WebIDBKey> >());
107 EXPECT_TRUE(callbacks.error_seen());
110 TEST_F(IndexedDBDispatcherTest, KeyAndValueSizeTest) {
111 const size_t kKeySize = 1024 * 1024;
113 const std::vector<char> data(kMaxIDBValueSizeInBytes - kKeySize);
114 const WebData value(&data.front(), data.size());
115 const WebVector<WebBlobInfo> web_blob_info;
116 const IndexedDBKey key(
117 base::string16(kKeySize / sizeof(base::string16::value_type), 'x'));
119 const int32 ipc_dummy_id = -1;
120 const int64 transaction_id = 1;
121 const int64 object_store_id = 2;
123 MockCallbacks callbacks;
124 IndexedDBDispatcher dispatcher(thread_safe_sender_.get());
125 dispatcher.RequestIDBDatabasePut(ipc_dummy_id,
126 transaction_id,
127 object_store_id,
128 value,
129 web_blob_info,
130 key,
131 blink::WebIDBPutModeAddOrUpdate,
132 &callbacks,
133 WebVector<long long>(),
134 WebVector<WebVector<WebIDBKey> >());
136 EXPECT_TRUE(callbacks.error_seen());
139 namespace {
141 class CursorCallbacks : public WebIDBCallbacks {
142 public:
143 explicit CursorCallbacks(scoped_ptr<WebIDBCursor>* cursor)
144 : cursor_(cursor) {}
146 void onSuccess(const WebIDBValue&) override {}
147 void onSuccess(WebIDBCursor* cursor,
148 const WebIDBKey& key,
149 const WebIDBKey& primaryKey,
150 const WebData& value,
151 const WebVector<WebBlobInfo>&) override {
152 cursor_->reset(cursor);
155 private:
156 scoped_ptr<WebIDBCursor>* cursor_;
158 DISALLOW_COPY_AND_ASSIGN(CursorCallbacks);
161 } // namespace
163 TEST_F(IndexedDBDispatcherTest, CursorTransactionId) {
164 const int32 ipc_database_id = -1;
165 const int64 transaction_id = 1234;
166 const int64 object_store_id = 2;
167 const int32 index_id = 3;
168 const blink::WebIDBCursorDirection direction =
169 blink::WebIDBCursorDirectionNext;
170 const bool key_only = false;
172 MockDispatcher dispatcher(thread_safe_sender_.get());
174 // First case: successful cursor open.
176 scoped_ptr<WebIDBCursor> cursor;
177 EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
179 // Make a cursor request. This should record the transaction id.
180 dispatcher.RequestIDBDatabaseOpenCursor(ipc_database_id,
181 transaction_id,
182 object_store_id,
183 index_id,
184 IndexedDBKeyRange(),
185 direction,
186 key_only,
187 blink::WebIDBTaskTypeNormal,
188 new CursorCallbacks(&cursor));
190 // Verify that the transaction id was captured.
191 EXPECT_EQ(1UL, dispatcher.cursor_transaction_ids_.size());
192 EXPECT_FALSE(cursor.get());
194 int32 ipc_callbacks_id = dispatcher.cursor_transaction_ids_.begin()->first;
196 IndexedDBMsg_CallbacksSuccessIDBCursor_Params params;
197 params.ipc_thread_id = dispatcher.CurrentWorkerId();
198 params.ipc_callbacks_id = ipc_callbacks_id;
200 // Now simululate the cursor response.
201 params.ipc_cursor_id = WebIDBCursorImpl::kInvalidCursorId;
202 dispatcher.OnSuccessOpenCursor(params);
204 EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
206 EXPECT_TRUE(cursor.get());
208 WebIDBCursorImpl* impl = static_cast<WebIDBCursorImpl*>(cursor.get());
210 // This is the primary expectation of this test: the transaction id was
211 // applied to the cursor.
212 EXPECT_EQ(transaction_id, impl->transaction_id());
215 // Second case: null cursor (no data in range)
217 scoped_ptr<WebIDBCursor> cursor;
218 EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
220 // Make a cursor request. This should record the transaction id.
221 dispatcher.RequestIDBDatabaseOpenCursor(ipc_database_id,
222 transaction_id,
223 object_store_id,
224 index_id,
225 IndexedDBKeyRange(),
226 direction,
227 key_only,
228 blink::WebIDBTaskTypeNormal,
229 new CursorCallbacks(&cursor));
231 // Verify that the transaction id was captured.
232 EXPECT_EQ(1UL, dispatcher.cursor_transaction_ids_.size());
233 EXPECT_FALSE(cursor.get());
235 int32 ipc_callbacks_id = dispatcher.cursor_transaction_ids_.begin()->first;
237 // Now simululate a "null cursor" response.
238 IndexedDBMsg_CallbacksSuccessValue_Params params;
239 params.ipc_thread_id = dispatcher.CurrentWorkerId();
240 params.ipc_callbacks_id = ipc_callbacks_id;
241 dispatcher.OnSuccessValue(params);
243 // Ensure the map result was deleted.
244 EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
245 EXPECT_FALSE(cursor.get());
249 namespace {
251 class MockCursor : public WebIDBCursorImpl {
252 public:
253 MockCursor(int32 ipc_cursor_id,
254 int64 transaction_id,
255 ThreadSafeSender* thread_safe_sender)
256 : WebIDBCursorImpl(ipc_cursor_id, transaction_id, thread_safe_sender),
257 reset_count_(0) {}
259 // This method is virtual so it can be overridden in unit tests.
260 void ResetPrefetchCache() override { ++reset_count_; }
262 int reset_count() const { return reset_count_; }
264 private:
265 int reset_count_;
267 DISALLOW_COPY_AND_ASSIGN(MockCursor);
270 } // namespace
272 TEST_F(IndexedDBDispatcherTest, CursorReset) {
273 scoped_ptr<WebIDBCursor> cursor;
274 MockDispatcher dispatcher(thread_safe_sender_.get());
276 const int32 ipc_database_id = 0;
277 const int32 object_store_id = 0;
278 const int32 index_id = 0;
279 const bool key_only = false;
280 const int cursor1_ipc_id = 1;
281 const int cursor2_ipc_id = 2;
282 const int other_cursor_ipc_id = 2;
283 const int cursor1_transaction_id = 1;
284 const int cursor2_transaction_id = 2;
285 const int other_transaction_id = 3;
287 scoped_ptr<MockCursor> cursor1(
288 new MockCursor(WebIDBCursorImpl::kInvalidCursorId,
289 cursor1_transaction_id,
290 thread_safe_sender_.get()));
292 scoped_ptr<MockCursor> cursor2(
293 new MockCursor(WebIDBCursorImpl::kInvalidCursorId,
294 cursor2_transaction_id,
295 thread_safe_sender_.get()));
297 dispatcher.cursors_[cursor1_ipc_id] = cursor1.get();
298 dispatcher.cursors_[cursor2_ipc_id] = cursor2.get();
300 EXPECT_EQ(0, cursor1->reset_count());
301 EXPECT_EQ(0, cursor2->reset_count());
303 // Other transaction:
304 dispatcher.RequestIDBDatabaseGet(ipc_database_id,
305 other_transaction_id,
306 object_store_id,
307 index_id,
308 IndexedDBKeyRange(),
309 key_only,
310 new MockCallbacks());
312 EXPECT_EQ(0, cursor1->reset_count());
313 EXPECT_EQ(0, cursor2->reset_count());
315 // Same transaction:
316 dispatcher.RequestIDBDatabaseGet(ipc_database_id,
317 cursor1_transaction_id,
318 object_store_id,
319 index_id,
320 IndexedDBKeyRange(),
321 key_only,
322 new MockCallbacks());
324 EXPECT_EQ(1, cursor1->reset_count());
325 EXPECT_EQ(0, cursor2->reset_count());
327 // Same transaction and same cursor:
328 dispatcher.RequestIDBCursorContinue(IndexedDBKey(),
329 IndexedDBKey(),
330 new MockCallbacks(),
331 cursor1_ipc_id,
332 cursor1_transaction_id);
334 EXPECT_EQ(1, cursor1->reset_count());
335 EXPECT_EQ(0, cursor2->reset_count());
337 // Same transaction and different cursor:
338 dispatcher.RequestIDBCursorContinue(IndexedDBKey(),
339 IndexedDBKey(),
340 new MockCallbacks(),
341 other_cursor_ipc_id,
342 cursor1_transaction_id);
344 EXPECT_EQ(2, cursor1->reset_count());
345 EXPECT_EQ(0, cursor2->reset_count());
347 cursor1.reset();
348 cursor2.reset();
351 } // namespace content