Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / content / child / indexed_db / webidbcursor_impl_unittest.cc
blob69fa803b9fe4dc84d4b34edf38b2037a2ee4772a
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/thread_task_runner_handle.h"
7 #include "base/values.h"
8 #include "content/child/indexed_db/indexed_db_dispatcher.h"
9 #include "content/child/indexed_db/indexed_db_key_builders.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 "ipc/ipc_sync_message_filter.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/WebKit/public/platform/WebData.h"
16 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBCallbacks.h"
18 using blink::WebBlobInfo;
19 using blink::WebData;
20 using blink::WebIDBCallbacks;
21 using blink::WebIDBDatabase;
22 using blink::WebIDBKey;
23 using blink::WebIDBKeyTypeNumber;
24 using blink::WebVector;
26 namespace content {
28 namespace {
30 class MockDispatcher : public IndexedDBDispatcher {
31 public:
32 explicit MockDispatcher(ThreadSafeSender* thread_safe_sender)
33 : IndexedDBDispatcher(thread_safe_sender),
34 prefetch_calls_(0),
35 last_prefetch_count_(0),
36 reset_calls_(0),
37 last_used_count_(0),
38 advance_calls_(0),
39 continue_calls_(0),
40 destroyed_cursor_id_(0) {}
42 void RequestIDBCursorPrefetch(int n,
43 WebIDBCallbacks* callbacks,
44 int32 ipc_cursor_id) override {
45 ++prefetch_calls_;
46 last_prefetch_count_ = n;
47 callbacks_.reset(callbacks);
50 void RequestIDBCursorPrefetchReset(int used_prefetches,
51 int unused_prefetches,
52 int32 ipc_cursor_id) override {
53 ++reset_calls_;
54 last_used_count_ = used_prefetches;
57 void RequestIDBCursorAdvance(unsigned long count,
58 WebIDBCallbacks* callbacks,
59 int32 ipc_cursor_id,
60 int64 transaction_id) override {
61 ++advance_calls_;
62 callbacks_.reset(callbacks);
65 void RequestIDBCursorContinue(const IndexedDBKey& key,
66 const IndexedDBKey& primary_key,
67 WebIDBCallbacks* callbacks,
68 int32 ipc_cursor_id,
69 int64 transaction_id) override {
70 ++continue_calls_;
71 callbacks_.reset(callbacks);
74 void CursorDestroyed(int32 ipc_cursor_id) override {
75 destroyed_cursor_id_ = ipc_cursor_id;
78 int prefetch_calls() { return prefetch_calls_; }
79 int last_prefetch_count() { return last_prefetch_count_; }
80 int reset_calls() { return reset_calls_; }
81 int last_used_count() { return last_used_count_; }
82 int advance_calls() { return advance_calls_; }
83 int continue_calls() { return continue_calls_; }
84 int32 destroyed_cursor_id() { return destroyed_cursor_id_; }
86 private:
87 int prefetch_calls_;
88 int last_prefetch_count_;
89 int reset_calls_;
90 int last_used_count_;
91 int advance_calls_;
92 int continue_calls_;
93 int32 destroyed_cursor_id_;
94 scoped_ptr<WebIDBCallbacks> callbacks_;
97 class MockContinueCallbacks : public WebIDBCallbacks {
98 public:
99 MockContinueCallbacks(IndexedDBKey* key = 0,
100 WebVector<WebBlobInfo>* webBlobInfo = 0)
101 : key_(key), web_blob_info_(webBlobInfo) {}
103 void onSuccess(const WebIDBKey& key,
104 const WebIDBKey& primaryKey,
105 const WebData& value,
106 const WebVector<WebBlobInfo>& webBlobInfo) override {
107 if (key_)
108 *key_ = IndexedDBKeyBuilder::Build(key);
109 if (web_blob_info_)
110 *web_blob_info_ = webBlobInfo;
113 private:
114 IndexedDBKey* key_;
115 WebVector<WebBlobInfo>* web_blob_info_;
118 class MockSyncMessageFilter : public IPC::SyncMessageFilter {
119 public:
120 MockSyncMessageFilter()
121 : SyncMessageFilter(nullptr, false /* is_channel_send_thread_safe */) {}
123 private:
124 ~MockSyncMessageFilter() override {}
127 } // namespace
129 class WebIDBCursorImplTest : public testing::Test {
130 public:
131 WebIDBCursorImplTest() {
132 null_key_.assignNull();
133 thread_safe_sender_ = new ThreadSafeSender(
134 base::ThreadTaskRunnerHandle::Get(), new MockSyncMessageFilter);
135 dispatcher_ =
136 make_scoped_ptr(new MockDispatcher(thread_safe_sender_.get()));
139 protected:
140 base::MessageLoop message_loop_;
141 WebIDBKey null_key_;
142 scoped_refptr<ThreadSafeSender> thread_safe_sender_;
143 scoped_ptr<MockDispatcher> dispatcher_;
145 private:
146 DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImplTest);
149 TEST_F(WebIDBCursorImplTest, PrefetchTest) {
150 const int64 transaction_id = 1;
152 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
153 transaction_id,
154 thread_safe_sender_.get());
156 // Call continue() until prefetching should kick in.
157 int continue_calls = 0;
158 EXPECT_EQ(dispatcher_->continue_calls(), 0);
159 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
160 cursor.continueFunction(null_key_, new MockContinueCallbacks());
161 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
162 EXPECT_EQ(0, dispatcher_->prefetch_calls());
165 // Do enough repetitions to verify that the count grows each time,
166 // but not so many that the maximum limit is hit.
167 const int kPrefetchRepetitions = 5;
169 int expected_key = 0;
170 int last_prefetch_count = 0;
171 for (int repetitions = 0; repetitions < kPrefetchRepetitions;
172 ++repetitions) {
173 // Initiate the prefetch
174 cursor.continueFunction(null_key_, new MockContinueCallbacks());
175 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
176 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
178 // Verify that the requested count has increased since last time.
179 int prefetch_count = dispatcher_->last_prefetch_count();
180 EXPECT_GT(prefetch_count, last_prefetch_count);
181 last_prefetch_count = prefetch_count;
183 // Fill the prefetch cache as requested.
184 std::vector<IndexedDBKey> keys;
185 std::vector<IndexedDBKey> primary_keys(prefetch_count);
186 std::vector<WebData> values(prefetch_count);
187 std::vector<WebVector<WebBlobInfo> > blob_info;
188 for (int i = 0; i < prefetch_count; ++i) {
189 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
190 blob_info.push_back(
191 WebVector<WebBlobInfo>(static_cast<size_t>(expected_key + i)));
193 cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
195 // Note that the real dispatcher would call cursor->CachedContinue()
196 // immediately after cursor->SetPrefetchData() to service the request
197 // that initiated the prefetch.
199 // Verify that the cache is used for subsequent continue() calls.
200 for (int i = 0; i < prefetch_count; ++i) {
201 IndexedDBKey key;
202 WebVector<WebBlobInfo> web_blob_info;
203 cursor.continueFunction(
204 null_key_, new MockContinueCallbacks(&key, &web_blob_info));
205 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
206 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
208 EXPECT_EQ(WebIDBKeyTypeNumber, key.type());
209 EXPECT_EQ(expected_key, static_cast<int>(web_blob_info.size()));
210 EXPECT_EQ(expected_key++, key.number());
215 EXPECT_EQ(dispatcher_->destroyed_cursor_id(),
216 WebIDBCursorImpl::kInvalidCursorId);
219 TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
220 const int64 transaction_id = 1;
221 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
222 transaction_id,
223 thread_safe_sender_.get());
225 // Call continue() until prefetching should kick in.
226 EXPECT_EQ(0, dispatcher_->continue_calls());
227 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
228 cursor.continueFunction(null_key_, new MockContinueCallbacks());
230 EXPECT_EQ(0, dispatcher_->prefetch_calls());
232 // Initiate the prefetch
233 cursor.continueFunction(null_key_, new MockContinueCallbacks());
235 EXPECT_EQ(1, dispatcher_->prefetch_calls());
236 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
237 dispatcher_->continue_calls());
238 EXPECT_EQ(0, dispatcher_->advance_calls());
240 const int prefetch_count = dispatcher_->last_prefetch_count();
242 // Fill the prefetch cache as requested.
243 int expected_key = 0;
244 std::vector<IndexedDBKey> keys;
245 std::vector<IndexedDBKey> primary_keys(prefetch_count);
246 std::vector<WebData> values(prefetch_count);
247 std::vector<WebVector<WebBlobInfo> > blob_info;
248 for (int i = 0; i < prefetch_count; ++i) {
249 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
250 blob_info.push_back(
251 WebVector<WebBlobInfo>(static_cast<size_t>(expected_key + i)));
253 cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
255 // Note that the real dispatcher would call cursor->CachedContinue()
256 // immediately after cursor->SetPrefetchData() to service the request
257 // that initiated the prefetch.
259 // Need at least this many in the cache for the test steps.
260 ASSERT_GE(prefetch_count, 5);
262 // IDBCursor.continue()
263 IndexedDBKey key;
264 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
265 EXPECT_EQ(0, key.number());
267 // IDBCursor.advance(1)
268 cursor.advance(1, new MockContinueCallbacks(&key));
269 EXPECT_EQ(1, key.number());
271 // IDBCursor.continue()
272 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
273 EXPECT_EQ(2, key.number());
275 // IDBCursor.advance(2)
276 cursor.advance(2, new MockContinueCallbacks(&key));
277 EXPECT_EQ(4, key.number());
279 EXPECT_EQ(0, dispatcher_->advance_calls());
281 // IDBCursor.advance(lots) - beyond the fetched amount
282 cursor.advance(WebIDBCursorImpl::kMaxPrefetchAmount,
283 new MockContinueCallbacks(&key));
284 EXPECT_EQ(1, dispatcher_->advance_calls());
285 EXPECT_EQ(1, dispatcher_->prefetch_calls());
286 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
287 dispatcher_->continue_calls());
290 TEST_F(WebIDBCursorImplTest, PrefetchReset) {
291 const int64 transaction_id = 1;
292 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
293 transaction_id,
294 thread_safe_sender_.get());
296 // Call continue() until prefetching should kick in.
297 int continue_calls = 0;
298 EXPECT_EQ(dispatcher_->continue_calls(), 0);
299 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
300 cursor.continueFunction(null_key_, new MockContinueCallbacks());
301 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
302 EXPECT_EQ(0, dispatcher_->prefetch_calls());
305 // Initiate the prefetch
306 cursor.continueFunction(null_key_, new MockContinueCallbacks());
307 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
308 EXPECT_EQ(1, dispatcher_->prefetch_calls());
309 EXPECT_EQ(0, dispatcher_->reset_calls());
311 // Now invalidate it
312 cursor.ResetPrefetchCache();
314 // No reset should have been sent since nothing has been received yet.
315 EXPECT_EQ(0, dispatcher_->reset_calls());
317 // Fill the prefetch cache as requested.
318 int prefetch_count = dispatcher_->last_prefetch_count();
319 std::vector<IndexedDBKey> keys(prefetch_count);
320 std::vector<IndexedDBKey> primary_keys(prefetch_count);
321 std::vector<WebData> values(prefetch_count);
322 std::vector<WebVector<WebBlobInfo> > blob_info(prefetch_count);
323 cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
325 // No reset should have been sent since prefetch data hasn't been used.
326 EXPECT_EQ(0, dispatcher_->reset_calls());
328 // The real dispatcher would call cursor->CachedContinue(), so do that:
329 scoped_ptr<WebIDBCallbacks> callbacks(new MockContinueCallbacks());
330 cursor.CachedContinue(callbacks.get());
332 // Now the cursor should have reset the rest of the cache.
333 EXPECT_EQ(1, dispatcher_->reset_calls());
334 EXPECT_EQ(1, dispatcher_->last_used_count());
337 } // namespace content