Added unit test for DevTools' ephemeral port support.
[chromium-blink-merge.git] / content / child / indexed_db / webidbcursor_impl_unittest.cc
bloba131096be23a606db278bbd6797a119d3b10e1a8
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::WebBlobInfo;
18 using blink::WebData;
19 using blink::WebIDBCallbacks;
20 using blink::WebIDBDatabase;
21 using blink::WebIDBKey;
22 using blink::WebIDBKeyTypeNumber;
23 using blink::WebVector;
25 namespace content {
27 namespace {
29 class MockDispatcher : public IndexedDBDispatcher {
30 public:
31 MockDispatcher(ThreadSafeSender* thread_safe_sender)
32 : IndexedDBDispatcher(thread_safe_sender),
33 prefetch_calls_(0),
34 last_prefetch_count_(0),
35 reset_calls_(0),
36 last_used_count_(0),
37 advance_calls_(0),
38 continue_calls_(0),
39 destroyed_cursor_id_(0) {}
41 virtual void RequestIDBCursorPrefetch(int n,
42 WebIDBCallbacks* callbacks,
43 int32 ipc_cursor_id) OVERRIDE {
44 ++prefetch_calls_;
45 last_prefetch_count_ = n;
46 callbacks_.reset(callbacks);
49 virtual void RequestIDBCursorPrefetchReset(int used_prefetches,
50 int unused_prefetches,
51 int32 ipc_cursor_id) OVERRIDE {
52 ++reset_calls_;
53 last_used_count_ = used_prefetches;
56 virtual void RequestIDBCursorAdvance(unsigned long count,
57 WebIDBCallbacks* callbacks,
58 int32 ipc_cursor_id,
59 int64 transaction_id) OVERRIDE {
60 ++advance_calls_;
61 callbacks_.reset(callbacks);
64 virtual void RequestIDBCursorContinue(const IndexedDBKey& key,
65 const IndexedDBKey& primary_key,
66 WebIDBCallbacks* callbacks,
67 int32 ipc_cursor_id,
68 int64 transaction_id) OVERRIDE {
69 ++continue_calls_;
70 callbacks_.reset(callbacks);
73 virtual void CursorDestroyed(int32 ipc_cursor_id) OVERRIDE {
74 destroyed_cursor_id_ = ipc_cursor_id;
77 int prefetch_calls() { return prefetch_calls_; }
78 int last_prefetch_count() { return last_prefetch_count_; }
79 int reset_calls() { return reset_calls_; }
80 int last_used_count() { return last_used_count_; }
81 int advance_calls() { return advance_calls_; }
82 int continue_calls() { return continue_calls_; }
83 int32 destroyed_cursor_id() { return destroyed_cursor_id_; }
85 private:
86 int prefetch_calls_;
87 int last_prefetch_count_;
88 int reset_calls_;
89 int last_used_count_;
90 int advance_calls_;
91 int continue_calls_;
92 int32 destroyed_cursor_id_;
93 scoped_ptr<WebIDBCallbacks> callbacks_;
96 class MockContinueCallbacks : public WebIDBCallbacks {
97 public:
98 MockContinueCallbacks(IndexedDBKey* key = 0,
99 WebVector<WebBlobInfo>* webBlobInfo = 0)
100 : key_(key), webBlobInfo_(webBlobInfo) {}
102 virtual void onSuccess(const WebIDBKey& key,
103 const WebIDBKey& primaryKey,
104 const WebData& value,
105 const WebVector<WebBlobInfo>& webBlobInfo) OVERRIDE {
107 if (key_)
108 *key_ = IndexedDBKeyBuilder::Build(key);
109 if (webBlobInfo_)
110 *webBlobInfo_ = webBlobInfo;
113 private:
114 IndexedDBKey* key_;
115 WebVector<WebBlobInfo>* webBlobInfo_;
118 } // namespace
120 class WebIDBCursorImplTest : public testing::Test {
121 public:
122 WebIDBCursorImplTest() {
123 null_key_.assignNull();
124 sync_message_filter_ = new IPC::SyncMessageFilter(NULL);
125 thread_safe_sender_ = new ThreadSafeSender(
126 base::MessageLoopProxy::current(), sync_message_filter_.get());
127 dispatcher_ =
128 make_scoped_ptr(new MockDispatcher(thread_safe_sender_.get()));
131 protected:
132 WebIDBKey null_key_;
133 scoped_refptr<ThreadSafeSender> thread_safe_sender_;
134 scoped_ptr<MockDispatcher> dispatcher_;
136 private:
137 scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
139 DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImplTest);
142 TEST_F(WebIDBCursorImplTest, PrefetchTest) {
144 const int64 transaction_id = 1;
146 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
147 transaction_id,
148 thread_safe_sender_.get());
150 // Call continue() until prefetching should kick in.
151 int continue_calls = 0;
152 EXPECT_EQ(dispatcher_->continue_calls(), 0);
153 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
154 cursor.continueFunction(null_key_, new MockContinueCallbacks());
155 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
156 EXPECT_EQ(0, dispatcher_->prefetch_calls());
159 // Do enough repetitions to verify that the count grows each time,
160 // but not so many that the maximum limit is hit.
161 const int kPrefetchRepetitions = 5;
163 int expected_key = 0;
164 int last_prefetch_count = 0;
165 for (int repetitions = 0; repetitions < kPrefetchRepetitions;
166 ++repetitions) {
168 // Initiate the prefetch
169 cursor.continueFunction(null_key_, new MockContinueCallbacks());
170 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
171 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
173 // Verify that the requested count has increased since last time.
174 int prefetch_count = dispatcher_->last_prefetch_count();
175 EXPECT_GT(prefetch_count, last_prefetch_count);
176 last_prefetch_count = prefetch_count;
178 // Fill the prefetch cache as requested.
179 std::vector<IndexedDBKey> keys;
180 std::vector<IndexedDBKey> primary_keys(prefetch_count);
181 std::vector<WebData> values(prefetch_count);
182 std::vector<WebVector<WebBlobInfo> > blob_info;
183 for (int i = 0; i < prefetch_count; ++i) {
184 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
185 blob_info.push_back(
186 WebVector<WebBlobInfo>(static_cast<size_t>(expected_key + i)));
188 cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
190 // Note that the real dispatcher would call cursor->CachedContinue()
191 // immediately after cursor->SetPrefetchData() to service the request
192 // that initiated the prefetch.
194 // Verify that the cache is used for subsequent continue() calls.
195 for (int i = 0; i < prefetch_count; ++i) {
196 IndexedDBKey key;
197 WebVector<WebBlobInfo> web_blob_info;
198 cursor.continueFunction(
199 null_key_, new MockContinueCallbacks(&key, &web_blob_info));
200 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
201 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
203 EXPECT_EQ(WebIDBKeyTypeNumber, key.type());
204 EXPECT_EQ(expected_key, static_cast<int>(web_blob_info.size()));
205 EXPECT_EQ(expected_key++, key.number());
210 EXPECT_EQ(dispatcher_->destroyed_cursor_id(),
211 WebIDBCursorImpl::kInvalidCursorId);
214 TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
216 const int64 transaction_id = 1;
217 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
218 transaction_id,
219 thread_safe_sender_.get());
221 // Call continue() until prefetching should kick in.
222 EXPECT_EQ(0, dispatcher_->continue_calls());
223 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
224 cursor.continueFunction(null_key_, new MockContinueCallbacks());
226 EXPECT_EQ(0, dispatcher_->prefetch_calls());
228 // Initiate the prefetch
229 cursor.continueFunction(null_key_, new MockContinueCallbacks());
231 EXPECT_EQ(1, dispatcher_->prefetch_calls());
232 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
233 dispatcher_->continue_calls());
234 EXPECT_EQ(0, dispatcher_->advance_calls());
236 const int prefetch_count = dispatcher_->last_prefetch_count();
238 // Fill the prefetch cache as requested.
239 int expected_key = 0;
240 std::vector<IndexedDBKey> keys;
241 std::vector<IndexedDBKey> primary_keys(prefetch_count);
242 std::vector<WebData> values(prefetch_count);
243 std::vector<WebVector<WebBlobInfo> > blob_info;
244 for (int i = 0; i < prefetch_count; ++i) {
245 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
246 blob_info.push_back(
247 WebVector<WebBlobInfo>(static_cast<size_t>(expected_key + i)));
249 cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
251 // Note that the real dispatcher would call cursor->CachedContinue()
252 // immediately after cursor->SetPrefetchData() to service the request
253 // that initiated the prefetch.
255 // Need at least this many in the cache for the test steps.
256 ASSERT_GE(prefetch_count, 5);
258 // IDBCursor.continue()
259 IndexedDBKey key;
260 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
261 EXPECT_EQ(0, key.number());
263 // IDBCursor.advance(1)
264 cursor.advance(1, new MockContinueCallbacks(&key));
265 EXPECT_EQ(1, key.number());
267 // IDBCursor.continue()
268 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
269 EXPECT_EQ(2, key.number());
271 // IDBCursor.advance(2)
272 cursor.advance(2, new MockContinueCallbacks(&key));
273 EXPECT_EQ(4, key.number());
275 EXPECT_EQ(0, dispatcher_->advance_calls());
277 // IDBCursor.advance(lots) - beyond the fetched amount
278 cursor.advance(WebIDBCursorImpl::kMaxPrefetchAmount,
279 new MockContinueCallbacks(&key));
280 EXPECT_EQ(1, dispatcher_->advance_calls());
281 EXPECT_EQ(1, dispatcher_->prefetch_calls());
282 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
283 dispatcher_->continue_calls());
286 TEST_F(WebIDBCursorImplTest, PrefetchReset) {
287 const int64 transaction_id = 1;
288 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
289 transaction_id,
290 thread_safe_sender_.get());
292 // Call continue() until prefetching should kick in.
293 int continue_calls = 0;
294 EXPECT_EQ(dispatcher_->continue_calls(), 0);
295 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
296 cursor.continueFunction(null_key_, new MockContinueCallbacks());
297 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
298 EXPECT_EQ(0, dispatcher_->prefetch_calls());
301 // Initiate the prefetch
302 cursor.continueFunction(null_key_, new MockContinueCallbacks());
303 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
304 EXPECT_EQ(1, dispatcher_->prefetch_calls());
305 EXPECT_EQ(0, dispatcher_->reset_calls());
307 // Now invalidate it
308 cursor.ResetPrefetchCache();
310 // No reset should have been sent since nothing has been received yet.
311 EXPECT_EQ(0, dispatcher_->reset_calls());
313 // Fill the prefetch cache as requested.
314 int prefetch_count = dispatcher_->last_prefetch_count();
315 std::vector<IndexedDBKey> keys(prefetch_count);
316 std::vector<IndexedDBKey> primary_keys(prefetch_count);
317 std::vector<WebData> values(prefetch_count);
318 std::vector<WebVector<WebBlobInfo> > blob_info(prefetch_count);
319 cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
321 // No reset should have been sent since prefetch data hasn't been used.
322 EXPECT_EQ(0, dispatcher_->reset_calls());
324 // The real dispatcher would call cursor->CachedContinue(), so do that:
325 scoped_ptr<WebIDBCallbacks> callbacks(new MockContinueCallbacks());
326 cursor.CachedContinue(callbacks.get());
328 // Now the cursor should have reset the rest of the cache.
329 EXPECT_EQ(1, dispatcher_->reset_calls());
330 EXPECT_EQ(1, dispatcher_->last_used_count());
333 } // namespace content