Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / child / indexed_db / webidbcursor_impl_unittest.cc
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.
4
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"
16
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;
24
25 namespace content {
26
27 namespace {
28
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) {}
40
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);
47   }
48
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;
54   }
55
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);
62   }
63
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);
71   }
72
73   virtual void CursorDestroyed(int32 ipc_cursor_id) OVERRIDE {
74     destroyed_cursor_id_ = ipc_cursor_id;
75   }
76
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_; }
84
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_;
94 };
95
96 class MockContinueCallbacks : public WebIDBCallbacks {
97  public:
98   MockContinueCallbacks(IndexedDBKey* key = 0,
99                         WebVector<WebBlobInfo>* webBlobInfo = 0)
100       : key_(key), webBlobInfo_(webBlobInfo) {}
101
102   virtual void onSuccess(const WebIDBKey& key,
103                          const WebIDBKey& primaryKey,
104                          const WebData& value,
105                          const WebVector<WebBlobInfo>& webBlobInfo) OVERRIDE {
106
107     if (key_)
108       *key_ = IndexedDBKeyBuilder::Build(key);
109     if (webBlobInfo_)
110       *webBlobInfo_ = webBlobInfo;
111   }
112
113  private:
114   IndexedDBKey* key_;
115   WebVector<WebBlobInfo>* webBlobInfo_;
116 };
117
118 }  // namespace
119
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()));
129   }
130
131  protected:
132   WebIDBKey null_key_;
133   scoped_refptr<ThreadSafeSender> thread_safe_sender_;
134   scoped_ptr<MockDispatcher> dispatcher_;
135
136  private:
137   scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
138
139   DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImplTest);
140 };
141
142 TEST_F(WebIDBCursorImplTest, PrefetchTest) {
143
144   const int64 transaction_id = 1;
145   {
146     WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
147                             transaction_id,
148                             thread_safe_sender_.get());
149
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());
157     }
158
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;
162
163     int expected_key = 0;
164     int last_prefetch_count = 0;
165     for (int repetitions = 0; repetitions < kPrefetchRepetitions;
166          ++repetitions) {
167
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());
172
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;
177
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)));
187       }
188       cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
189
190       // Note that the real dispatcher would call cursor->CachedContinue()
191       // immediately after cursor->SetPrefetchData() to service the request
192       // that initiated the prefetch.
193
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());
202
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());
206       }
207     }
208   }
209
210   EXPECT_EQ(dispatcher_->destroyed_cursor_id(),
211             WebIDBCursorImpl::kInvalidCursorId);
212 }
213
214 TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
215
216   const int64 transaction_id = 1;
217   WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
218                           transaction_id,
219                           thread_safe_sender_.get());
220
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());
225   }
226   EXPECT_EQ(0, dispatcher_->prefetch_calls());
227
228   // Initiate the prefetch
229   cursor.continueFunction(null_key_, new MockContinueCallbacks());
230
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());
235
236   const int prefetch_count = dispatcher_->last_prefetch_count();
237
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)));
248   }
249   cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
250
251   // Note that the real dispatcher would call cursor->CachedContinue()
252   // immediately after cursor->SetPrefetchData() to service the request
253   // that initiated the prefetch.
254
255   // Need at least this many in the cache for the test steps.
256   ASSERT_GE(prefetch_count, 5);
257
258   // IDBCursor.continue()
259   IndexedDBKey key;
260   cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
261   EXPECT_EQ(0, key.number());
262
263   // IDBCursor.advance(1)
264   cursor.advance(1, new MockContinueCallbacks(&key));
265   EXPECT_EQ(1, key.number());
266
267   // IDBCursor.continue()
268   cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
269   EXPECT_EQ(2, key.number());
270
271   // IDBCursor.advance(2)
272   cursor.advance(2, new MockContinueCallbacks(&key));
273   EXPECT_EQ(4, key.number());
274
275   EXPECT_EQ(0, dispatcher_->advance_calls());
276
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());
284 }
285
286 TEST_F(WebIDBCursorImplTest, PrefetchReset) {
287   const int64 transaction_id = 1;
288   WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
289                           transaction_id,
290                           thread_safe_sender_.get());
291
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());
299   }
300
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());
306
307   // Now invalidate it
308   cursor.ResetPrefetchCache();
309
310   // No reset should have been sent since nothing has been received yet.
311   EXPECT_EQ(0, dispatcher_->reset_calls());
312
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);
320
321   // No reset should have been sent since prefetch data hasn't been used.
322   EXPECT_EQ(0, dispatcher_->reset_calls());
323
324   // The real dispatcher would call cursor->CachedContinue(), so do that:
325   scoped_ptr<WebIDBCallbacks> callbacks(new MockContinueCallbacks());
326   cursor.CachedContinue(callbacks.get());
327
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());
331 }
332
333 }  // namespace content