GPU workaround to simulate Out of Memory errors with large textures
[chromium-blink-merge.git] / content / child / indexed_db / webidbcursor_impl_unittest.cc
blob95d187b7f5307787d3db3e1960d6a20a00a8ad96
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 explicit 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 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 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 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 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 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), web_blob_info_(webBlobInfo) {}
102 virtual void onSuccess(const WebIDBKey& key,
103 const WebIDBKey& primaryKey,
104 const WebData& value,
105 const WebVector<WebBlobInfo>& webBlobInfo) override {
106 if (key_)
107 *key_ = IndexedDBKeyBuilder::Build(key);
108 if (web_blob_info_)
109 *web_blob_info_ = webBlobInfo;
112 private:
113 IndexedDBKey* key_;
114 WebVector<WebBlobInfo>* web_blob_info_;
117 } // namespace
119 class WebIDBCursorImplTest : public testing::Test {
120 public:
121 WebIDBCursorImplTest() {
122 null_key_.assignNull();
123 sync_message_filter_ = new IPC::SyncMessageFilter(NULL);
124 thread_safe_sender_ = new ThreadSafeSender(
125 base::MessageLoopProxy::current(), sync_message_filter_.get());
126 dispatcher_ =
127 make_scoped_ptr(new MockDispatcher(thread_safe_sender_.get()));
130 protected:
131 WebIDBKey null_key_;
132 scoped_refptr<ThreadSafeSender> thread_safe_sender_;
133 scoped_ptr<MockDispatcher> dispatcher_;
135 private:
136 scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
138 DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImplTest);
141 TEST_F(WebIDBCursorImplTest, PrefetchTest) {
142 const int64 transaction_id = 1;
144 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
145 transaction_id,
146 thread_safe_sender_.get());
148 // Call continue() until prefetching should kick in.
149 int continue_calls = 0;
150 EXPECT_EQ(dispatcher_->continue_calls(), 0);
151 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
152 cursor.continueFunction(null_key_, new MockContinueCallbacks());
153 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
154 EXPECT_EQ(0, dispatcher_->prefetch_calls());
157 // Do enough repetitions to verify that the count grows each time,
158 // but not so many that the maximum limit is hit.
159 const int kPrefetchRepetitions = 5;
161 int expected_key = 0;
162 int last_prefetch_count = 0;
163 for (int repetitions = 0; repetitions < kPrefetchRepetitions;
164 ++repetitions) {
165 // Initiate the prefetch
166 cursor.continueFunction(null_key_, new MockContinueCallbacks());
167 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
168 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
170 // Verify that the requested count has increased since last time.
171 int prefetch_count = dispatcher_->last_prefetch_count();
172 EXPECT_GT(prefetch_count, last_prefetch_count);
173 last_prefetch_count = prefetch_count;
175 // Fill the prefetch cache as requested.
176 std::vector<IndexedDBKey> keys;
177 std::vector<IndexedDBKey> primary_keys(prefetch_count);
178 std::vector<WebData> values(prefetch_count);
179 std::vector<WebVector<WebBlobInfo> > blob_info;
180 for (int i = 0; i < prefetch_count; ++i) {
181 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
182 blob_info.push_back(
183 WebVector<WebBlobInfo>(static_cast<size_t>(expected_key + i)));
185 cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
187 // Note that the real dispatcher would call cursor->CachedContinue()
188 // immediately after cursor->SetPrefetchData() to service the request
189 // that initiated the prefetch.
191 // Verify that the cache is used for subsequent continue() calls.
192 for (int i = 0; i < prefetch_count; ++i) {
193 IndexedDBKey key;
194 WebVector<WebBlobInfo> web_blob_info;
195 cursor.continueFunction(
196 null_key_, new MockContinueCallbacks(&key, &web_blob_info));
197 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
198 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
200 EXPECT_EQ(WebIDBKeyTypeNumber, key.type());
201 EXPECT_EQ(expected_key, static_cast<int>(web_blob_info.size()));
202 EXPECT_EQ(expected_key++, key.number());
207 EXPECT_EQ(dispatcher_->destroyed_cursor_id(),
208 WebIDBCursorImpl::kInvalidCursorId);
211 TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
212 const int64 transaction_id = 1;
213 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
214 transaction_id,
215 thread_safe_sender_.get());
217 // Call continue() until prefetching should kick in.
218 EXPECT_EQ(0, dispatcher_->continue_calls());
219 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
220 cursor.continueFunction(null_key_, new MockContinueCallbacks());
222 EXPECT_EQ(0, dispatcher_->prefetch_calls());
224 // Initiate the prefetch
225 cursor.continueFunction(null_key_, new MockContinueCallbacks());
227 EXPECT_EQ(1, dispatcher_->prefetch_calls());
228 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
229 dispatcher_->continue_calls());
230 EXPECT_EQ(0, dispatcher_->advance_calls());
232 const int prefetch_count = dispatcher_->last_prefetch_count();
234 // Fill the prefetch cache as requested.
235 int expected_key = 0;
236 std::vector<IndexedDBKey> keys;
237 std::vector<IndexedDBKey> primary_keys(prefetch_count);
238 std::vector<WebData> values(prefetch_count);
239 std::vector<WebVector<WebBlobInfo> > blob_info;
240 for (int i = 0; i < prefetch_count; ++i) {
241 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
242 blob_info.push_back(
243 WebVector<WebBlobInfo>(static_cast<size_t>(expected_key + i)));
245 cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
247 // Note that the real dispatcher would call cursor->CachedContinue()
248 // immediately after cursor->SetPrefetchData() to service the request
249 // that initiated the prefetch.
251 // Need at least this many in the cache for the test steps.
252 ASSERT_GE(prefetch_count, 5);
254 // IDBCursor.continue()
255 IndexedDBKey key;
256 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
257 EXPECT_EQ(0, key.number());
259 // IDBCursor.advance(1)
260 cursor.advance(1, new MockContinueCallbacks(&key));
261 EXPECT_EQ(1, key.number());
263 // IDBCursor.continue()
264 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
265 EXPECT_EQ(2, key.number());
267 // IDBCursor.advance(2)
268 cursor.advance(2, new MockContinueCallbacks(&key));
269 EXPECT_EQ(4, key.number());
271 EXPECT_EQ(0, dispatcher_->advance_calls());
273 // IDBCursor.advance(lots) - beyond the fetched amount
274 cursor.advance(WebIDBCursorImpl::kMaxPrefetchAmount,
275 new MockContinueCallbacks(&key));
276 EXPECT_EQ(1, dispatcher_->advance_calls());
277 EXPECT_EQ(1, dispatcher_->prefetch_calls());
278 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
279 dispatcher_->continue_calls());
282 TEST_F(WebIDBCursorImplTest, PrefetchReset) {
283 const int64 transaction_id = 1;
284 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
285 transaction_id,
286 thread_safe_sender_.get());
288 // Call continue() until prefetching should kick in.
289 int continue_calls = 0;
290 EXPECT_EQ(dispatcher_->continue_calls(), 0);
291 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
292 cursor.continueFunction(null_key_, new MockContinueCallbacks());
293 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
294 EXPECT_EQ(0, dispatcher_->prefetch_calls());
297 // Initiate the prefetch
298 cursor.continueFunction(null_key_, new MockContinueCallbacks());
299 EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
300 EXPECT_EQ(1, dispatcher_->prefetch_calls());
301 EXPECT_EQ(0, dispatcher_->reset_calls());
303 // Now invalidate it
304 cursor.ResetPrefetchCache();
306 // No reset should have been sent since nothing has been received yet.
307 EXPECT_EQ(0, dispatcher_->reset_calls());
309 // Fill the prefetch cache as requested.
310 int prefetch_count = dispatcher_->last_prefetch_count();
311 std::vector<IndexedDBKey> keys(prefetch_count);
312 std::vector<IndexedDBKey> primary_keys(prefetch_count);
313 std::vector<WebData> values(prefetch_count);
314 std::vector<WebVector<WebBlobInfo> > blob_info(prefetch_count);
315 cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
317 // No reset should have been sent since prefetch data hasn't been used.
318 EXPECT_EQ(0, dispatcher_->reset_calls());
320 // The real dispatcher would call cursor->CachedContinue(), so do that:
321 scoped_ptr<WebIDBCallbacks> callbacks(new MockContinueCallbacks());
322 cursor.CachedContinue(callbacks.get());
324 // Now the cursor should have reset the rest of the cache.
325 EXPECT_EQ(1, dispatcher_->reset_calls());
326 EXPECT_EQ(1, dispatcher_->last_used_count());
329 } // namespace content