Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / content / child / indexed_db / indexed_db_dispatcher_unittest.cc
blob6e72d7bf30b634c74d5929aad8fd69b8966b4433
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 class MockSyncMessageFilter : public IPC::SyncMessageFilter {
64 public:
65 MockSyncMessageFilter()
66 : SyncMessageFilter(nullptr, false /* is_channel_send_thread_safe */) {}
68 private:
69 ~MockSyncMessageFilter() override {}
72 } // namespace
74 class IndexedDBDispatcherTest : public testing::Test {
75 public:
76 IndexedDBDispatcherTest()
77 : thread_safe_sender_(new ThreadSafeSender(
78 base::ThreadTaskRunnerHandle::Get(), new MockSyncMessageFilter)) {}
80 void TearDown() override { blink::WebHeap::collectAllGarbageForTesting(); }
82 protected:
83 base::MessageLoop message_loop_;
84 scoped_refptr<ThreadSafeSender> thread_safe_sender_;
86 private:
87 DISALLOW_COPY_AND_ASSIGN(IndexedDBDispatcherTest);
90 TEST_F(IndexedDBDispatcherTest, ValueSizeTest) {
91 const std::vector<char> data(kMaxIDBValueSizeInBytes + 1);
92 const WebData value(&data.front(), data.size());
93 const WebVector<WebBlobInfo> web_blob_info;
94 const int32 ipc_dummy_id = -1;
95 const int64 transaction_id = 1;
96 const int64 object_store_id = 2;
98 MockCallbacks callbacks;
99 IndexedDBDispatcher dispatcher(thread_safe_sender_.get());
100 IndexedDBKey key(0, blink::WebIDBKeyTypeNumber);
101 dispatcher.RequestIDBDatabasePut(ipc_dummy_id,
102 transaction_id,
103 object_store_id,
104 value,
105 web_blob_info,
106 key,
107 blink::WebIDBPutModeAddOrUpdate,
108 &callbacks,
109 WebVector<long long>(),
110 WebVector<WebVector<WebIDBKey> >());
112 EXPECT_TRUE(callbacks.error_seen());
115 TEST_F(IndexedDBDispatcherTest, KeyAndValueSizeTest) {
116 const size_t kKeySize = 1024 * 1024;
118 const std::vector<char> data(kMaxIDBValueSizeInBytes - kKeySize);
119 const WebData value(&data.front(), data.size());
120 const WebVector<WebBlobInfo> web_blob_info;
121 const IndexedDBKey key(
122 base::string16(kKeySize / sizeof(base::string16::value_type), 'x'));
124 const int32 ipc_dummy_id = -1;
125 const int64 transaction_id = 1;
126 const int64 object_store_id = 2;
128 MockCallbacks callbacks;
129 IndexedDBDispatcher dispatcher(thread_safe_sender_.get());
130 dispatcher.RequestIDBDatabasePut(ipc_dummy_id,
131 transaction_id,
132 object_store_id,
133 value,
134 web_blob_info,
135 key,
136 blink::WebIDBPutModeAddOrUpdate,
137 &callbacks,
138 WebVector<long long>(),
139 WebVector<WebVector<WebIDBKey> >());
141 EXPECT_TRUE(callbacks.error_seen());
144 namespace {
146 class CursorCallbacks : public WebIDBCallbacks {
147 public:
148 explicit CursorCallbacks(scoped_ptr<WebIDBCursor>* cursor)
149 : cursor_(cursor) {}
151 void onSuccess(const WebIDBValue&) override {}
152 void onSuccess(WebIDBCursor* cursor,
153 const WebIDBKey& key,
154 const WebIDBKey& primaryKey,
155 const WebData& value,
156 const WebVector<WebBlobInfo>&) override {
157 cursor_->reset(cursor);
160 private:
161 scoped_ptr<WebIDBCursor>* cursor_;
163 DISALLOW_COPY_AND_ASSIGN(CursorCallbacks);
166 } // namespace
168 TEST_F(IndexedDBDispatcherTest, CursorTransactionId) {
169 const int32 ipc_database_id = -1;
170 const int64 transaction_id = 1234;
171 const int64 object_store_id = 2;
172 const int32 index_id = 3;
173 const blink::WebIDBCursorDirection direction =
174 blink::WebIDBCursorDirectionNext;
175 const bool key_only = false;
177 MockDispatcher dispatcher(thread_safe_sender_.get());
179 // First case: successful cursor open.
181 scoped_ptr<WebIDBCursor> cursor;
182 EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
184 // Make a cursor request. This should record the transaction id.
185 dispatcher.RequestIDBDatabaseOpenCursor(ipc_database_id,
186 transaction_id,
187 object_store_id,
188 index_id,
189 IndexedDBKeyRange(),
190 direction,
191 key_only,
192 blink::WebIDBTaskTypeNormal,
193 new CursorCallbacks(&cursor));
195 // Verify that the transaction id was captured.
196 EXPECT_EQ(1UL, dispatcher.cursor_transaction_ids_.size());
197 EXPECT_FALSE(cursor.get());
199 int32 ipc_callbacks_id = dispatcher.cursor_transaction_ids_.begin()->first;
201 IndexedDBMsg_CallbacksSuccessIDBCursor_Params params;
202 params.ipc_thread_id = dispatcher.CurrentWorkerId();
203 params.ipc_callbacks_id = ipc_callbacks_id;
205 // Now simululate the cursor response.
206 params.ipc_cursor_id = WebIDBCursorImpl::kInvalidCursorId;
207 dispatcher.OnSuccessOpenCursor(params);
209 EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
211 EXPECT_TRUE(cursor.get());
213 WebIDBCursorImpl* impl = static_cast<WebIDBCursorImpl*>(cursor.get());
215 // This is the primary expectation of this test: the transaction id was
216 // applied to the cursor.
217 EXPECT_EQ(transaction_id, impl->transaction_id());
220 // Second case: null cursor (no data in range)
222 scoped_ptr<WebIDBCursor> cursor;
223 EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
225 // Make a cursor request. This should record the transaction id.
226 dispatcher.RequestIDBDatabaseOpenCursor(ipc_database_id,
227 transaction_id,
228 object_store_id,
229 index_id,
230 IndexedDBKeyRange(),
231 direction,
232 key_only,
233 blink::WebIDBTaskTypeNormal,
234 new CursorCallbacks(&cursor));
236 // Verify that the transaction id was captured.
237 EXPECT_EQ(1UL, dispatcher.cursor_transaction_ids_.size());
238 EXPECT_FALSE(cursor.get());
240 int32 ipc_callbacks_id = dispatcher.cursor_transaction_ids_.begin()->first;
242 // Now simululate a "null cursor" response.
243 IndexedDBMsg_CallbacksSuccessValue_Params params;
244 params.ipc_thread_id = dispatcher.CurrentWorkerId();
245 params.ipc_callbacks_id = ipc_callbacks_id;
246 dispatcher.OnSuccessValue(params);
248 // Ensure the map result was deleted.
249 EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
250 EXPECT_FALSE(cursor.get());
254 namespace {
256 class MockCursor : public WebIDBCursorImpl {
257 public:
258 MockCursor(int32 ipc_cursor_id,
259 int64 transaction_id,
260 ThreadSafeSender* thread_safe_sender)
261 : WebIDBCursorImpl(ipc_cursor_id, transaction_id, thread_safe_sender),
262 reset_count_(0) {}
264 // This method is virtual so it can be overridden in unit tests.
265 void ResetPrefetchCache() override { ++reset_count_; }
267 int reset_count() const { return reset_count_; }
269 private:
270 int reset_count_;
272 DISALLOW_COPY_AND_ASSIGN(MockCursor);
275 } // namespace
277 TEST_F(IndexedDBDispatcherTest, CursorReset) {
278 scoped_ptr<WebIDBCursor> cursor;
279 MockDispatcher dispatcher(thread_safe_sender_.get());
281 const int32 ipc_database_id = 0;
282 const int32 object_store_id = 0;
283 const int32 index_id = 0;
284 const bool key_only = false;
285 const int cursor1_ipc_id = 1;
286 const int cursor2_ipc_id = 2;
287 const int other_cursor_ipc_id = 2;
288 const int cursor1_transaction_id = 1;
289 const int cursor2_transaction_id = 2;
290 const int other_transaction_id = 3;
292 scoped_ptr<MockCursor> cursor1(
293 new MockCursor(WebIDBCursorImpl::kInvalidCursorId,
294 cursor1_transaction_id,
295 thread_safe_sender_.get()));
297 scoped_ptr<MockCursor> cursor2(
298 new MockCursor(WebIDBCursorImpl::kInvalidCursorId,
299 cursor2_transaction_id,
300 thread_safe_sender_.get()));
302 dispatcher.cursors_[cursor1_ipc_id] = cursor1.get();
303 dispatcher.cursors_[cursor2_ipc_id] = cursor2.get();
305 EXPECT_EQ(0, cursor1->reset_count());
306 EXPECT_EQ(0, cursor2->reset_count());
308 // Other transaction:
309 dispatcher.RequestIDBDatabaseGet(ipc_database_id,
310 other_transaction_id,
311 object_store_id,
312 index_id,
313 IndexedDBKeyRange(),
314 key_only,
315 new MockCallbacks());
317 EXPECT_EQ(0, cursor1->reset_count());
318 EXPECT_EQ(0, cursor2->reset_count());
320 // Same transaction:
321 dispatcher.RequestIDBDatabaseGet(ipc_database_id,
322 cursor1_transaction_id,
323 object_store_id,
324 index_id,
325 IndexedDBKeyRange(),
326 key_only,
327 new MockCallbacks());
329 EXPECT_EQ(1, cursor1->reset_count());
330 EXPECT_EQ(0, cursor2->reset_count());
332 // Same transaction and same cursor:
333 dispatcher.RequestIDBCursorContinue(IndexedDBKey(),
334 IndexedDBKey(),
335 new MockCallbacks(),
336 cursor1_ipc_id,
337 cursor1_transaction_id);
339 EXPECT_EQ(1, cursor1->reset_count());
340 EXPECT_EQ(0, cursor2->reset_count());
342 // Same transaction and different cursor:
343 dispatcher.RequestIDBCursorContinue(IndexedDBKey(),
344 IndexedDBKey(),
345 new MockCallbacks(),
346 other_cursor_ipc_id,
347 cursor1_transaction_id);
349 EXPECT_EQ(2, cursor1->reset_count());
350 EXPECT_EQ(0, cursor2->reset_count());
352 cursor1.reset();
353 cursor2.reset();
356 } // namespace content