Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / child / indexed_db / indexed_db_dispatcher_unittest.cc
blob4f29998f02ce0c4894eddd78ea882e93c6bc130b
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/message_loop/message_loop_proxy.h"
7 #include "base/values.h"
8 #include "content/child/indexed_db/indexed_db_dispatcher.h"
9 #include "content/child/indexed_db/webidbcursor_impl.h"
10 #include "content/child/thread_safe_sender.h"
11 #include "content/common/indexed_db/indexed_db_key.h"
12 #include "content/common/indexed_db/indexed_db_key_range.h"
13 #include "content/common/indexed_db/indexed_db_messages.h"
14 #include "ipc/ipc_sync_message_filter.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/WebKit/public/platform/WebBlobInfo.h"
17 #include "third_party/WebKit/public/platform/WebData.h"
18 #include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
19 #include "third_party/WebKit/public/web/WebHeap.h"
21 using blink::WebBlobInfo;
22 using blink::WebData;
23 using blink::WebIDBCallbacks;
24 using blink::WebIDBCursor;
25 using blink::WebIDBDatabase;
26 using blink::WebIDBDatabaseError;
27 using blink::WebIDBKey;
28 using blink::WebVector;
30 namespace content {
31 namespace {
33 class MockCallbacks : public WebIDBCallbacks {
34 public:
35 MockCallbacks() : error_seen_(false) {}
37 virtual void onError(const WebIDBDatabaseError&) { error_seen_ = true; }
39 bool error_seen() const { return error_seen_; }
41 private:
42 bool error_seen_;
44 DISALLOW_COPY_AND_ASSIGN(MockCallbacks);
47 class MockDispatcher : public IndexedDBDispatcher {
48 public:
49 explicit MockDispatcher(ThreadSafeSender* sender)
50 : IndexedDBDispatcher(sender) {}
52 bool Send(IPC::Message* msg) override {
53 delete msg;
54 return true;
57 private:
58 DISALLOW_COPY_AND_ASSIGN(MockDispatcher);
61 } // namespace
63 class IndexedDBDispatcherTest : public testing::Test {
64 public:
65 IndexedDBDispatcherTest()
66 : message_loop_proxy_(base::MessageLoopProxy::current()),
67 sync_message_filter_(new IPC::SyncMessageFilter(NULL)),
68 thread_safe_sender_(new ThreadSafeSender(message_loop_proxy_.get(),
69 sync_message_filter_.get())) {}
71 void TearDown() override { blink::WebHeap::collectAllGarbageForTesting(); }
73 protected:
74 scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
75 scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
76 scoped_refptr<ThreadSafeSender> thread_safe_sender_;
78 private:
79 DISALLOW_COPY_AND_ASSIGN(IndexedDBDispatcherTest);
82 TEST_F(IndexedDBDispatcherTest, ValueSizeTest) {
83 const std::vector<char> data(kMaxIDBValueSizeInBytes + 1);
84 const WebData value(&data.front(), data.size());
85 const WebVector<WebBlobInfo> web_blob_info;
86 const int32 ipc_dummy_id = -1;
87 const int64 transaction_id = 1;
88 const int64 object_store_id = 2;
90 MockCallbacks callbacks;
91 IndexedDBDispatcher dispatcher(thread_safe_sender_.get());
92 IndexedDBKey key(0, blink::WebIDBKeyTypeNumber);
93 dispatcher.RequestIDBDatabasePut(ipc_dummy_id,
94 transaction_id,
95 object_store_id,
96 value,
97 web_blob_info,
98 key,
99 blink::WebIDBPutModeAddOrUpdate,
100 &callbacks,
101 WebVector<long long>(),
102 WebVector<WebVector<WebIDBKey> >());
104 EXPECT_TRUE(callbacks.error_seen());
107 TEST_F(IndexedDBDispatcherTest, KeyAndValueSizeTest) {
108 const size_t kKeySize = 1024 * 1024;
110 const std::vector<char> data(kMaxIDBValueSizeInBytes - kKeySize);
111 const WebData value(&data.front(), data.size());
112 const WebVector<WebBlobInfo> web_blob_info;
113 const IndexedDBKey key(
114 base::string16(kKeySize / sizeof(base::string16::value_type), 'x'));
116 const int32 ipc_dummy_id = -1;
117 const int64 transaction_id = 1;
118 const int64 object_store_id = 2;
120 MockCallbacks callbacks;
121 IndexedDBDispatcher dispatcher(thread_safe_sender_.get());
122 dispatcher.RequestIDBDatabasePut(ipc_dummy_id,
123 transaction_id,
124 object_store_id,
125 value,
126 web_blob_info,
127 key,
128 blink::WebIDBPutModeAddOrUpdate,
129 &callbacks,
130 WebVector<long long>(),
131 WebVector<WebVector<WebIDBKey> >());
133 EXPECT_TRUE(callbacks.error_seen());
136 namespace {
138 class CursorCallbacks : public WebIDBCallbacks {
139 public:
140 explicit CursorCallbacks(scoped_ptr<WebIDBCursor>* cursor)
141 : cursor_(cursor) {}
143 virtual void onSuccess(const WebData&,
144 const WebVector<WebBlobInfo>&) override {}
145 virtual void onSuccess(WebIDBCursor* cursor,
146 const WebIDBKey& key,
147 const WebIDBKey& primaryKey,
148 const WebData& value,
149 const WebVector<WebBlobInfo>&) override {
150 cursor_->reset(cursor);
153 private:
154 scoped_ptr<WebIDBCursor>* cursor_;
156 DISALLOW_COPY_AND_ASSIGN(CursorCallbacks);
159 } // namespace
161 TEST_F(IndexedDBDispatcherTest, CursorTransactionId) {
162 const int32 ipc_database_id = -1;
163 const int64 transaction_id = 1234;
164 const int64 object_store_id = 2;
165 const int32 index_id = 3;
166 const blink::WebIDBCursorDirection direction =
167 blink::WebIDBCursorDirectionNext;
168 const bool key_only = false;
170 MockDispatcher dispatcher(thread_safe_sender_.get());
172 // First case: successful cursor open.
174 scoped_ptr<WebIDBCursor> cursor;
175 EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
177 // Make a cursor request. This should record the transaction id.
178 dispatcher.RequestIDBDatabaseOpenCursor(ipc_database_id,
179 transaction_id,
180 object_store_id,
181 index_id,
182 IndexedDBKeyRange(),
183 direction,
184 key_only,
185 blink::WebIDBTaskTypeNormal,
186 new CursorCallbacks(&cursor));
188 // Verify that the transaction id was captured.
189 EXPECT_EQ(1UL, dispatcher.cursor_transaction_ids_.size());
190 EXPECT_FALSE(cursor.get());
192 int32 ipc_callbacks_id = dispatcher.cursor_transaction_ids_.begin()->first;
194 IndexedDBMsg_CallbacksSuccessIDBCursor_Params params;
195 params.ipc_thread_id = dispatcher.CurrentWorkerId();
196 params.ipc_callbacks_id = ipc_callbacks_id;
198 // Now simululate the cursor response.
199 params.ipc_cursor_id = WebIDBCursorImpl::kInvalidCursorId;
200 dispatcher.OnSuccessOpenCursor(params);
202 EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
204 EXPECT_TRUE(cursor.get());
206 WebIDBCursorImpl* impl = static_cast<WebIDBCursorImpl*>(cursor.get());
208 // This is the primary expectation of this test: the transaction id was
209 // applied to the cursor.
210 EXPECT_EQ(transaction_id, impl->transaction_id());
213 // Second case: null cursor (no data in range)
215 scoped_ptr<WebIDBCursor> cursor;
216 EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
218 // Make a cursor request. This should record the transaction id.
219 dispatcher.RequestIDBDatabaseOpenCursor(ipc_database_id,
220 transaction_id,
221 object_store_id,
222 index_id,
223 IndexedDBKeyRange(),
224 direction,
225 key_only,
226 blink::WebIDBTaskTypeNormal,
227 new CursorCallbacks(&cursor));
229 // Verify that the transaction id was captured.
230 EXPECT_EQ(1UL, dispatcher.cursor_transaction_ids_.size());
231 EXPECT_FALSE(cursor.get());
233 int32 ipc_callbacks_id = dispatcher.cursor_transaction_ids_.begin()->first;
235 // Now simululate a "null cursor" response.
236 IndexedDBMsg_CallbacksSuccessValue_Params params;
237 params.ipc_thread_id = dispatcher.CurrentWorkerId();
238 params.ipc_callbacks_id = ipc_callbacks_id;
239 dispatcher.OnSuccessValue(params);
241 // Ensure the map result was deleted.
242 EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
243 EXPECT_FALSE(cursor.get());
247 namespace {
249 class MockCursor : public WebIDBCursorImpl {
250 public:
251 MockCursor(int32 ipc_cursor_id,
252 int64 transaction_id,
253 ThreadSafeSender* thread_safe_sender)
254 : WebIDBCursorImpl(ipc_cursor_id, transaction_id, thread_safe_sender),
255 reset_count_(0) {}
257 // This method is virtual so it can be overridden in unit tests.
258 void ResetPrefetchCache() override { ++reset_count_; }
260 int reset_count() const { return reset_count_; }
262 private:
263 int reset_count_;
265 DISALLOW_COPY_AND_ASSIGN(MockCursor);
268 } // namespace
270 TEST_F(IndexedDBDispatcherTest, CursorReset) {
271 scoped_ptr<WebIDBCursor> cursor;
272 MockDispatcher dispatcher(thread_safe_sender_.get());
274 const int32 ipc_database_id = 0;
275 const int32 object_store_id = 0;
276 const int32 index_id = 0;
277 const bool key_only = false;
278 const int cursor1_ipc_id = 1;
279 const int cursor2_ipc_id = 2;
280 const int other_cursor_ipc_id = 2;
281 const int cursor1_transaction_id = 1;
282 const int cursor2_transaction_id = 2;
283 const int other_transaction_id = 3;
285 scoped_ptr<MockCursor> cursor1(
286 new MockCursor(WebIDBCursorImpl::kInvalidCursorId,
287 cursor1_transaction_id,
288 thread_safe_sender_.get()));
290 scoped_ptr<MockCursor> cursor2(
291 new MockCursor(WebIDBCursorImpl::kInvalidCursorId,
292 cursor2_transaction_id,
293 thread_safe_sender_.get()));
295 dispatcher.cursors_[cursor1_ipc_id] = cursor1.get();
296 dispatcher.cursors_[cursor2_ipc_id] = cursor2.get();
298 EXPECT_EQ(0, cursor1->reset_count());
299 EXPECT_EQ(0, cursor2->reset_count());
301 // Other transaction:
302 dispatcher.RequestIDBDatabaseGet(ipc_database_id,
303 other_transaction_id,
304 object_store_id,
305 index_id,
306 IndexedDBKeyRange(),
307 key_only,
308 new MockCallbacks());
310 EXPECT_EQ(0, cursor1->reset_count());
311 EXPECT_EQ(0, cursor2->reset_count());
313 // Same transaction:
314 dispatcher.RequestIDBDatabaseGet(ipc_database_id,
315 cursor1_transaction_id,
316 object_store_id,
317 index_id,
318 IndexedDBKeyRange(),
319 key_only,
320 new MockCallbacks());
322 EXPECT_EQ(1, cursor1->reset_count());
323 EXPECT_EQ(0, cursor2->reset_count());
325 // Same transaction and same cursor:
326 dispatcher.RequestIDBCursorContinue(IndexedDBKey(),
327 IndexedDBKey(),
328 new MockCallbacks(),
329 cursor1_ipc_id,
330 cursor1_transaction_id);
332 EXPECT_EQ(1, cursor1->reset_count());
333 EXPECT_EQ(0, cursor2->reset_count());
335 // Same transaction and different cursor:
336 dispatcher.RequestIDBCursorContinue(IndexedDBKey(),
337 IndexedDBKey(),
338 new MockCallbacks(),
339 other_cursor_ipc_id,
340 cursor1_transaction_id);
342 EXPECT_EQ(2, cursor1->reset_count());
343 EXPECT_EQ(0, cursor2->reset_count());
345 cursor1.reset();
346 cursor2.reset();
349 } // namespace content