IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / child / indexed_db / webidbcursor_impl_unittest.cc
blob111595048cb52eaffa7aee16dee97bc9a1e61700
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/values.h"
7 #include "content/child/indexed_db/indexed_db_dispatcher.h"
8 #include "content/child/indexed_db/indexed_db_key_builders.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 "ipc/ipc_sync_message_filter.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/WebKit/public/platform/WebData.h"
15 #include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
17 using blink::WebData;
18 using blink::WebIDBCallbacks;
19 using blink::WebIDBDatabase;
20 using blink::WebIDBKey;
21 using blink::WebIDBKeyTypeNumber;
23 namespace content {
25 namespace {
27 class MockDispatcher : public IndexedDBDispatcher {
28 public:
29 MockDispatcher(ThreadSafeSender* thread_safe_sender)
30 : IndexedDBDispatcher(thread_safe_sender),
31 prefetch_calls_(0),
32 last_prefetch_count_(0),
33 reset_calls_(0),
34 last_used_count_(0),
35 advance_calls_(0),
36 continue_calls_(0),
37 destroyed_cursor_id_(0) {}
39 virtual void RequestIDBCursorPrefetch(int n,
40 WebIDBCallbacks* callbacks,
41 int32 ipc_cursor_id) OVERRIDE {
42 ++prefetch_calls_;
43 last_prefetch_count_ = n;
44 callbacks_.reset(callbacks);
47 virtual void RequestIDBCursorPrefetchReset(int used_prefetches,
48 int unused_prefetches,
49 int32 ipc_cursor_id) OVERRIDE {
50 ++reset_calls_;
51 last_used_count_ = used_prefetches;
54 virtual void RequestIDBCursorAdvance(unsigned long count,
55 WebIDBCallbacks* callbacks,
56 int32 ipc_cursor_id) OVERRIDE {
57 ++advance_calls_;
58 callbacks_.reset(callbacks);
61 virtual void RequestIDBCursorContinue(const IndexedDBKey& key,
62 const IndexedDBKey& primary_key,
63 WebIDBCallbacks* callbacks,
64 int32 ipc_cursor_id) OVERRIDE {
65 ++continue_calls_;
66 callbacks_.reset(callbacks);
69 virtual void CursorDestroyed(int32 ipc_cursor_id) OVERRIDE {
70 destroyed_cursor_id_ = ipc_cursor_id;
73 int prefetch_calls() { return prefetch_calls_; }
74 int last_prefetch_count() { return last_prefetch_count_; }
75 int reset_calls() { return reset_calls_; }
76 int last_used_count() { return last_used_count_; }
77 int advance_calls() { return advance_calls_; }
78 int continue_calls() { return continue_calls_; }
79 int32 destroyed_cursor_id() { return destroyed_cursor_id_; }
81 private:
82 int prefetch_calls_;
83 int last_prefetch_count_;
84 int reset_calls_;
85 int last_used_count_;
86 int advance_calls_;
87 int continue_calls_;
88 int32 destroyed_cursor_id_;
89 scoped_ptr<WebIDBCallbacks> callbacks_;
92 class MockContinueCallbacks : public WebIDBCallbacks {
93 public:
94 MockContinueCallbacks(IndexedDBKey* key = 0) : key_(key) {}
96 virtual void onSuccess(const WebIDBKey& key,
97 const WebIDBKey& primaryKey,
98 const WebData& value) {
100 if (key_)
101 *key_ = IndexedDBKeyBuilder::Build(key);
104 private:
105 IndexedDBKey* key_;
108 } // namespace
110 class WebIDBCursorImplTest : public testing::Test {
111 public:
112 WebIDBCursorImplTest() {
113 null_key_.assignNull();
114 sync_message_filter_ = new IPC::SyncMessageFilter(NULL);
115 thread_safe_sender_ = new ThreadSafeSender(
116 base::MessageLoopProxy::current(), sync_message_filter_.get());
117 dispatcher_ =
118 make_scoped_ptr(new MockDispatcher(thread_safe_sender_.get()));
121 protected:
122 WebIDBKey null_key_;
123 scoped_refptr<ThreadSafeSender> thread_safe_sender_;
124 scoped_ptr<MockDispatcher> dispatcher_;
126 private:
127 scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
129 DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImplTest);
132 TEST_F(WebIDBCursorImplTest, PrefetchTest) {
135 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
136 thread_safe_sender_.get());
138 // Call continue() until prefetching should kick in.
139 int continue_calls = 0;
140 EXPECT_EQ(dispatcher_->continue_calls(), 0);
141 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
142 cursor.continueFunction(null_key_, new MockContinueCallbacks());
143 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
144 EXPECT_EQ(0, dispatcher_->prefetch_calls());
147 // Do enough repetitions to verify that the count grows each time,
148 // but not so many that the maximum limit is hit.
149 const int kPrefetchRepetitions = 5;
151 int expected_key = 0;
152 int last_prefetch_count = 0;
153 for (int repetitions = 0; repetitions < kPrefetchRepetitions;
154 ++repetitions) {
156 // Initiate the prefetch
157 cursor.continueFunction(null_key_, new MockContinueCallbacks());
158 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
159 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
161 // Verify that the requested count has increased since last time.
162 int prefetch_count = dispatcher_->last_prefetch_count();
163 EXPECT_GT(prefetch_count, last_prefetch_count);
164 last_prefetch_count = prefetch_count;
166 // Fill the prefetch cache as requested.
167 std::vector<IndexedDBKey> keys;
168 std::vector<IndexedDBKey> primary_keys(prefetch_count);
169 std::vector<WebData> values(prefetch_count);
170 for (int i = 0; i < prefetch_count; ++i) {
171 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
173 cursor.SetPrefetchData(keys, primary_keys, values);
175 // Note that the real dispatcher would call cursor->CachedContinue()
176 // immediately after cursor->SetPrefetchData() to service the request
177 // that initiated the prefetch.
179 // Verify that the cache is used for subsequent continue() calls.
180 for (int i = 0; i < prefetch_count; ++i) {
181 IndexedDBKey key;
182 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
183 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
184 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
186 EXPECT_EQ(WebIDBKeyTypeNumber, key.type());
187 EXPECT_EQ(expected_key++, key.number());
192 EXPECT_EQ(dispatcher_->destroyed_cursor_id(),
193 WebIDBCursorImpl::kInvalidCursorId);
196 TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
198 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
199 thread_safe_sender_.get());
201 // Call continue() until prefetching should kick in.
202 EXPECT_EQ(0, dispatcher_->continue_calls());
203 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
204 cursor.continueFunction(null_key_, new MockContinueCallbacks());
206 EXPECT_EQ(0, dispatcher_->prefetch_calls());
208 // Initiate the prefetch
209 cursor.continueFunction(null_key_, new MockContinueCallbacks());
211 EXPECT_EQ(1, dispatcher_->prefetch_calls());
212 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
213 dispatcher_->continue_calls());
214 EXPECT_EQ(0, dispatcher_->advance_calls());
216 const int prefetch_count = dispatcher_->last_prefetch_count();
218 // Fill the prefetch cache as requested.
219 int expected_key = 0;
220 std::vector<IndexedDBKey> keys;
221 std::vector<IndexedDBKey> primary_keys(prefetch_count);
222 std::vector<WebData> values(prefetch_count);
223 for (int i = 0; i < prefetch_count; ++i) {
224 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
226 cursor.SetPrefetchData(keys, primary_keys, values);
228 // Note that the real dispatcher would call cursor->CachedContinue()
229 // immediately after cursor->SetPrefetchData() to service the request
230 // that initiated the prefetch.
232 // Need at least this many in the cache for the test steps.
233 ASSERT_GE(prefetch_count, 5);
235 // IDBCursor.continue()
236 IndexedDBKey key;
237 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
238 EXPECT_EQ(0, key.number());
240 // IDBCursor.advance(1)
241 cursor.advance(1, new MockContinueCallbacks(&key));
242 EXPECT_EQ(1, key.number());
244 // IDBCursor.continue()
245 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
246 EXPECT_EQ(2, key.number());
248 // IDBCursor.advance(2)
249 cursor.advance(2, new MockContinueCallbacks(&key));
250 EXPECT_EQ(4, key.number());
252 EXPECT_EQ(0, dispatcher_->advance_calls());
254 // IDBCursor.advance(lots) - beyond the fetched amount
255 cursor.advance(WebIDBCursorImpl::kMaxPrefetchAmount,
256 new MockContinueCallbacks(&key));
257 EXPECT_EQ(1, dispatcher_->advance_calls());
258 EXPECT_EQ(1, dispatcher_->prefetch_calls());
259 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
260 dispatcher_->continue_calls());
263 TEST_F(WebIDBCursorImplTest, PrefetchReset) {
264 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
265 thread_safe_sender_.get());
267 // Call continue() until prefetching should kick in.
268 int continue_calls = 0;
269 EXPECT_EQ(dispatcher_->continue_calls(), 0);
270 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
271 cursor.continueFunction(null_key_, new MockContinueCallbacks());
272 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
273 EXPECT_EQ(0, dispatcher_->prefetch_calls());
276 // Initiate the prefetch
277 cursor.continueFunction(null_key_, new MockContinueCallbacks());
278 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
279 EXPECT_EQ(1, dispatcher_->prefetch_calls());
280 EXPECT_EQ(0, dispatcher_->reset_calls());
282 // Now invalidate it
283 cursor.ResetPrefetchCache();
285 // No reset should have been sent since nothing has been received yet.
286 EXPECT_EQ(0, dispatcher_->reset_calls());
288 // Fill the prefetch cache as requested.
289 int prefetch_count = dispatcher_->last_prefetch_count();
290 std::vector<IndexedDBKey> keys(prefetch_count);
291 std::vector<IndexedDBKey> primary_keys(prefetch_count);
292 std::vector<WebData> values(prefetch_count);
293 cursor.SetPrefetchData(keys, primary_keys, values);
295 // No reset should have been sent since prefetch data hasn't been used.
296 EXPECT_EQ(0, dispatcher_->reset_calls());
298 // The real dispatcher would call cursor->CachedContinue(), so do that:
299 scoped_ptr<WebIDBCallbacks> callbacks(new MockContinueCallbacks());
300 cursor.CachedContinue(callbacks.get());
302 // Now the cursor should have reset the rest of the cache.
303 EXPECT_EQ(1, dispatcher_->reset_calls());
304 EXPECT_EQ(1, dispatcher_->last_used_count());
307 } // namespace content