Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(278)

Side by Side Diff: content/child/indexed_db/proxy_webidbcursor_impl_unittest.cc

Issue 104663007: IndexedDB: Optimize IDBCursor.advance() if it occurs within prefetched range (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added unit test Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/memory/scoped_ptr.h" 5 #include "base/memory/scoped_ptr.h"
6 #include "base/values.h" 6 #include "base/values.h"
7 #include "content/child/indexed_db/indexed_db_dispatcher.h" 7 #include "content/child/indexed_db/indexed_db_dispatcher.h"
8 #include "content/child/indexed_db/indexed_db_key_builders.h" 8 #include "content/child/indexed_db/indexed_db_key_builders.h"
9 #include "content/child/indexed_db/proxy_webidbcursor_impl.h" 9 #include "content/child/indexed_db/proxy_webidbcursor_impl.h"
10 #include "content/child/thread_safe_sender.h" 10 #include "content/child/thread_safe_sender.h"
(...skipping 12 matching lines...) Expand all
23 namespace content { 23 namespace content {
24 24
25 namespace { 25 namespace {
26 26
27 class MockDispatcher : public IndexedDBDispatcher { 27 class MockDispatcher : public IndexedDBDispatcher {
28 public: 28 public:
29 MockDispatcher(ThreadSafeSender* thread_safe_sender) 29 MockDispatcher(ThreadSafeSender* thread_safe_sender)
30 : IndexedDBDispatcher(thread_safe_sender), 30 : IndexedDBDispatcher(thread_safe_sender),
31 prefetch_calls_(0), 31 prefetch_calls_(0),
32 last_prefetch_count_(0), 32 last_prefetch_count_(0),
33 advance_calls_(0),
33 continue_calls_(0), 34 continue_calls_(0),
34 destroyed_cursor_id_(0) {} 35 destroyed_cursor_id_(0) {}
35 36
36 virtual void RequestIDBCursorPrefetch(int n, 37 virtual void RequestIDBCursorPrefetch(int n,
37 WebIDBCallbacks* callbacks, 38 WebIDBCallbacks* callbacks,
38 int32 ipc_cursor_id) OVERRIDE { 39 int32 ipc_cursor_id) OVERRIDE {
39 ++prefetch_calls_; 40 ++prefetch_calls_;
40 last_prefetch_count_ = n; 41 last_prefetch_count_ = n;
41 callbacks_.reset(callbacks); 42 callbacks_.reset(callbacks);
42 } 43 }
43 44
45 virtual void RequestIDBCursorAdvance(unsigned long count,
46 WebIDBCallbacks* callbacks,
47 int32 ipc_cursor_id) OVERRIDE {
48 ++advance_calls_;
49 callbacks_.reset(callbacks);
50 }
51
44 virtual void RequestIDBCursorContinue(const IndexedDBKey& key, 52 virtual void RequestIDBCursorContinue(const IndexedDBKey& key,
45 const IndexedDBKey& primary_key, 53 const IndexedDBKey& primary_key,
46 WebIDBCallbacks* callbacks, 54 WebIDBCallbacks* callbacks,
47 int32 ipc_cursor_id) OVERRIDE { 55 int32 ipc_cursor_id) OVERRIDE {
48 ++continue_calls_; 56 ++continue_calls_;
49 callbacks_.reset(callbacks); 57 callbacks_.reset(callbacks);
50 } 58 }
51 59
52 virtual void CursorDestroyed(int32 ipc_cursor_id) OVERRIDE { 60 virtual void CursorDestroyed(int32 ipc_cursor_id) OVERRIDE {
53 destroyed_cursor_id_ = ipc_cursor_id; 61 destroyed_cursor_id_ = ipc_cursor_id;
54 } 62 }
55 63
56 int prefetch_calls() { return prefetch_calls_; } 64 int prefetch_calls() { return prefetch_calls_; }
65 int advance_calls() { return advance_calls_; }
57 int continue_calls() { return continue_calls_; } 66 int continue_calls() { return continue_calls_; }
58 int last_prefetch_count() { return last_prefetch_count_; } 67 int last_prefetch_count() { return last_prefetch_count_; }
59 int32 destroyed_cursor_id() { return destroyed_cursor_id_; } 68 int32 destroyed_cursor_id() { return destroyed_cursor_id_; }
60 69
61 private: 70 private:
62 int prefetch_calls_; 71 int prefetch_calls_;
63 int last_prefetch_count_; 72 int last_prefetch_count_;
73 int advance_calls_;
64 int continue_calls_; 74 int continue_calls_;
65 int32 destroyed_cursor_id_; 75 int32 destroyed_cursor_id_;
66 scoped_ptr<WebIDBCallbacks> callbacks_; 76 scoped_ptr<WebIDBCallbacks> callbacks_;
67 }; 77 };
68 78
69 class MockContinueCallbacks : public WebIDBCallbacks { 79 class MockContinueCallbacks : public WebIDBCallbacks {
70 public: 80 public:
71 MockContinueCallbacks(IndexedDBKey* key = 0) : key_(key) {} 81 MockContinueCallbacks(IndexedDBKey* key = 0) : key_(key) {}
72 82
73 virtual void onSuccess(const WebIDBKey& key, 83 virtual void onSuccess(const WebIDBKey& key,
74 const WebIDBKey& primaryKey, 84 const WebIDBKey& primaryKey,
75 const WebData& value) { 85 const WebData& value) {
76 86
77 if (key_) 87 if (key_)
78 *key_ = IndexedDBKeyBuilder::Build(key); 88 *key_ = IndexedDBKeyBuilder::Build(key);
79 } 89 }
80 90
81 private: 91 private:
82 IndexedDBKey* key_; 92 IndexedDBKey* key_;
83 }; 93 };
84 94
85 } // namespace 95 } // namespace
86 96
87 TEST(RendererWebIDBCursorImplTest, PrefetchTest) { 97 class RendererWebIDBCursorImplTest : public testing::Test {
98 public:
99 RendererWebIDBCursorImplTest() {
100 null_key_.assignNull();
101 sync_message_filter_ = new IPC::SyncMessageFilter(NULL);
102 thread_safe_sender_ = new ThreadSafeSender(
103 base::MessageLoopProxy::current(), sync_message_filter_.get());
104 dispatcher_ =
105 make_scoped_ptr(new MockDispatcher(thread_safe_sender_.get()));
106 }
88 107
89 WebIDBKey null_key; 108 protected:
90 null_key.assignNull(); 109 WebIDBKey null_key_;
110 scoped_refptr<ThreadSafeSender> thread_safe_sender_;
111 scoped_ptr<MockDispatcher> dispatcher_;
91 112
92 scoped_refptr<base::MessageLoopProxy> message_loop_proxy( 113 private:
93 base::MessageLoopProxy::current()); 114 scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
94 scoped_refptr<IPC::SyncMessageFilter> sync_message_filter(
95 new IPC::SyncMessageFilter(NULL));
96 scoped_refptr<ThreadSafeSender> thread_safe_sender(new ThreadSafeSender(
97 message_loop_proxy.get(), sync_message_filter.get()));
98 115
99 MockDispatcher dispatcher(thread_safe_sender.get()); 116 DISALLOW_COPY_AND_ASSIGN(RendererWebIDBCursorImplTest);
117 };
118
119 TEST_F(RendererWebIDBCursorImplTest, PrefetchTest) {
100 120
101 { 121 {
102 RendererWebIDBCursorImpl cursor(RendererWebIDBCursorImpl::kInvalidCursorId, 122 RendererWebIDBCursorImpl cursor(RendererWebIDBCursorImpl::kInvalidCursorId,
103 thread_safe_sender.get()); 123 thread_safe_sender_.get());
104 124
105 // Call continue() until prefetching should kick in. 125 // Call continue() until prefetching should kick in.
106 int continue_calls = 0; 126 int continue_calls = 0;
107 EXPECT_EQ(dispatcher.continue_calls(), 0); 127 EXPECT_EQ(dispatcher_->continue_calls(), 0);
108 for (int i = 0; i < RendererWebIDBCursorImpl::kPrefetchContinueThreshold; 128 for (int i = 0; i < RendererWebIDBCursorImpl::kPrefetchContinueThreshold;
109 ++i) { 129 ++i) {
110 cursor.continueFunction(null_key, new MockContinueCallbacks()); 130 cursor.continueFunction(null_key_, new MockContinueCallbacks());
111 EXPECT_EQ(++continue_calls, dispatcher.continue_calls()); 131 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
112 EXPECT_EQ(0, dispatcher.prefetch_calls()); 132 EXPECT_EQ(0, dispatcher_->prefetch_calls());
113 } 133 }
114 134
115 // Do enough repetitions to verify that the count grows each time, 135 // Do enough repetitions to verify that the count grows each time,
116 // but not so many that the maximum limit is hit. 136 // but not so many that the maximum limit is hit.
117 const int kPrefetchRepetitions = 5; 137 const int kPrefetchRepetitions = 5;
118 138
119 int expected_key = 0; 139 int expected_key = 0;
120 int last_prefetch_count = 0; 140 int last_prefetch_count = 0;
121 for (int repetitions = 0; repetitions < kPrefetchRepetitions; 141 for (int repetitions = 0; repetitions < kPrefetchRepetitions;
122 ++repetitions) { 142 ++repetitions) {
123 143
124 // Initiate the prefetch 144 // Initiate the prefetch
125 cursor.continueFunction(null_key, new MockContinueCallbacks()); 145 cursor.continueFunction(null_key_, new MockContinueCallbacks());
126 EXPECT_EQ(continue_calls, dispatcher.continue_calls()); 146 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
127 EXPECT_EQ(repetitions + 1, dispatcher.prefetch_calls()); 147 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
128 148
129 // Verify that the requested count has increased since last time. 149 // Verify that the requested count has increased since last time.
130 int prefetch_count = dispatcher.last_prefetch_count(); 150 int prefetch_count = dispatcher_->last_prefetch_count();
131 EXPECT_GT(prefetch_count, last_prefetch_count); 151 EXPECT_GT(prefetch_count, last_prefetch_count);
132 last_prefetch_count = prefetch_count; 152 last_prefetch_count = prefetch_count;
133 153
134 // Fill the prefetch cache as requested. 154 // Fill the prefetch cache as requested.
135 std::vector<IndexedDBKey> keys; 155 std::vector<IndexedDBKey> keys;
136 std::vector<IndexedDBKey> primary_keys(prefetch_count); 156 std::vector<IndexedDBKey> primary_keys(prefetch_count);
137 std::vector<WebData> values(prefetch_count); 157 std::vector<WebData> values(prefetch_count);
138 for (int i = 0; i < prefetch_count; ++i) { 158 for (int i = 0; i < prefetch_count; ++i) {
139 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber)); 159 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
140 } 160 }
141 cursor.SetPrefetchData(keys, primary_keys, values); 161 cursor.SetPrefetchData(keys, primary_keys, values);
142 162
143 // Note that the real dispatcher would call cursor->CachedContinue() 163 // Note that the real dispatcher would call cursor->CachedContinue()
144 // immediately after cursor->SetPrefetchData() to service the request 164 // immediately after cursor->SetPrefetchData() to service the request
145 // that initiated the prefetch. 165 // that initiated the prefetch.
146 166
147 // Verify that the cache is used for subsequent continue() calls. 167 // Verify that the cache is used for subsequent continue() calls.
148 for (int i = 0; i < prefetch_count; ++i) { 168 for (int i = 0; i < prefetch_count; ++i) {
149 IndexedDBKey key; 169 IndexedDBKey key;
150 cursor.continueFunction(null_key, new MockContinueCallbacks(&key)); 170 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
151 EXPECT_EQ(continue_calls, dispatcher.continue_calls()); 171 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
152 EXPECT_EQ(repetitions + 1, dispatcher.prefetch_calls()); 172 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
153 173
154 EXPECT_EQ(WebIDBKeyTypeNumber, key.type()); 174 EXPECT_EQ(WebIDBKeyTypeNumber, key.type());
155 EXPECT_EQ(expected_key++, key.number()); 175 EXPECT_EQ(expected_key++, key.number());
156 } 176 }
157 } 177 }
158 } 178 }
159 179
160 EXPECT_EQ(dispatcher.destroyed_cursor_id(), 180 EXPECT_EQ(dispatcher_->destroyed_cursor_id(),
161 RendererWebIDBCursorImpl::kInvalidCursorId); 181 RendererWebIDBCursorImpl::kInvalidCursorId);
162 } 182 }
163 183
184 TEST_F(RendererWebIDBCursorImplTest, AdvancePrefetchTest) {
185
186 RendererWebIDBCursorImpl cursor(RendererWebIDBCursorImpl::kInvalidCursorId,
187 thread_safe_sender_.get());
188
189 // Call continue() until prefetching should kick in.
190 EXPECT_EQ(0, dispatcher_->continue_calls());
191 for (int i = 0; i < RendererWebIDBCursorImpl::kPrefetchContinueThreshold;
192 ++i) {
193 cursor.continueFunction(null_key_, new MockContinueCallbacks());
194 }
195 EXPECT_EQ(0, dispatcher_->prefetch_calls());
196
197 // Initiate the prefetch
198 cursor.continueFunction(null_key_, new MockContinueCallbacks());
199
200 EXPECT_EQ(1, dispatcher_->prefetch_calls());
201 EXPECT_EQ(RendererWebIDBCursorImpl::kPrefetchContinueThreshold,
202 dispatcher_->continue_calls());
203 EXPECT_EQ(0, dispatcher_->advance_calls());
204
205 const int prefetch_count = dispatcher_->last_prefetch_count();
206
207 // Fill the prefetch cache as requested.
208 int expected_key = 0;
209 std::vector<IndexedDBKey> keys;
210 std::vector<IndexedDBKey> primary_keys(prefetch_count);
211 std::vector<WebData> values(prefetch_count);
212 for (int i = 0; i < prefetch_count; ++i) {
213 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
214 }
215 cursor.SetPrefetchData(keys, primary_keys, values);
216
217 // Note that the real dispatcher would call cursor->CachedContinue()
218 // immediately after cursor->SetPrefetchData() to service the request
219 // that initiated the prefetch.
220
221 // Need at least this many in the cache for the test steps.
222 ASSERT_GE(prefetch_count, 5);
223
224 // IDBCursor.continue()
225 IndexedDBKey key;
226 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
227 EXPECT_EQ(0, key.number());
228
229 // IDBCursor.advance(1)
230 cursor.advance(1, new MockContinueCallbacks(&key));
231 EXPECT_EQ(1, key.number());
232
233 // IDBCursor.continue()
234 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
235 EXPECT_EQ(2, key.number());
236
237 // IDBCursor.advance(2)
238 cursor.advance(2, new MockContinueCallbacks(&key));
239 EXPECT_EQ(4, key.number());
240
241 EXPECT_EQ(0, dispatcher_->advance_calls());
242
243 // IDBCursor.advance(lots) - beyond the fetched amount
244 cursor.advance(RendererWebIDBCursorImpl::kMaxPrefetchAmount,
245 new MockContinueCallbacks(&key));
246 EXPECT_EQ(1, dispatcher_->advance_calls());
247 EXPECT_EQ(1, dispatcher_->prefetch_calls());
248 EXPECT_EQ(RendererWebIDBCursorImpl::kPrefetchContinueThreshold,
249 dispatcher_->continue_calls());
250 }
251
164 } // namespace content 252 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698