Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / child / indexed_db / indexed_db_dispatcher_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/message_loop/message_loop_proxy.h"
7 #include "base/values.h"
8 #include "content/child/indexed_db/indexed_db_dispatcher.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 "content/common/indexed_db/indexed_db_key_range.h"
13 #include "content/common/indexed_db/indexed_db_messages.h"
14 #include "ipc/ipc_sync_message_filter.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/WebKit/public/platform/WebBlobInfo.h"
17 #include "third_party/WebKit/public/platform/WebData.h"
18 #include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
19
20 using blink::WebBlobInfo;
21 using blink::WebData;
22 using blink::WebIDBCallbacks;
23 using blink::WebIDBCursor;
24 using blink::WebIDBDatabase;
25 using blink::WebIDBDatabaseError;
26 using blink::WebIDBKey;
27 using blink::WebVector;
28
29 namespace content {
30 namespace {
31
32 class MockCallbacks : public WebIDBCallbacks {
33  public:
34   MockCallbacks() : error_seen_(false) {}
35
36   virtual void onError(const WebIDBDatabaseError&) { error_seen_ = true; }
37
38   bool error_seen() const { return error_seen_; }
39
40  private:
41   bool error_seen_;
42
43   DISALLOW_COPY_AND_ASSIGN(MockCallbacks);
44 };
45
46 class MockDispatcher : public IndexedDBDispatcher {
47  public:
48   explicit MockDispatcher(ThreadSafeSender* sender)
49       : IndexedDBDispatcher(sender) {}
50
51   virtual bool Send(IPC::Message* msg) OVERRIDE {
52     delete msg;
53     return true;
54   }
55
56  private:
57   DISALLOW_COPY_AND_ASSIGN(MockDispatcher);
58 };
59
60 }  // namespace
61
62 class IndexedDBDispatcherTest : public testing::Test {
63  public:
64   IndexedDBDispatcherTest()
65       : message_loop_proxy_(base::MessageLoopProxy::current()),
66         sync_message_filter_(new IPC::SyncMessageFilter(NULL)),
67         thread_safe_sender_(new ThreadSafeSender(message_loop_proxy_.get(),
68                                                  sync_message_filter_.get())) {}
69
70  protected:
71   scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
72   scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
73   scoped_refptr<ThreadSafeSender> thread_safe_sender_;
74
75  private:
76   DISALLOW_COPY_AND_ASSIGN(IndexedDBDispatcherTest);
77 };
78
79 TEST_F(IndexedDBDispatcherTest, ValueSizeTest) {
80   const std::vector<char> data(kMaxIDBValueSizeInBytes + 1);
81   const WebData value(&data.front(), data.size());
82   const WebVector<WebBlobInfo> web_blob_info;
83   const int32 ipc_dummy_id = -1;
84   const int64 transaction_id = 1;
85   const int64 object_store_id = 2;
86
87   MockCallbacks callbacks;
88   IndexedDBDispatcher dispatcher(thread_safe_sender_.get());
89   IndexedDBKey key(0, blink::WebIDBKeyTypeNumber);
90   dispatcher.RequestIDBDatabasePut(ipc_dummy_id,
91                                    transaction_id,
92                                    object_store_id,
93                                    value,
94                                    web_blob_info,
95                                    key,
96                                    blink::WebIDBPutModeAddOrUpdate,
97                                    &callbacks,
98                                    WebVector<long long>(),
99                                    WebVector<WebVector<WebIDBKey> >());
100
101   EXPECT_TRUE(callbacks.error_seen());
102 }
103
104 TEST_F(IndexedDBDispatcherTest, KeyAndValueSizeTest) {
105   const size_t kKeySize = 1024 * 1024;
106
107   const std::vector<char> data(kMaxIDBValueSizeInBytes - kKeySize);
108   const WebData value(&data.front(), data.size());
109   const WebVector<WebBlobInfo> web_blob_info;
110   const IndexedDBKey key(
111       base::string16(kKeySize / sizeof(base::string16::value_type), 'x'));
112
113   const int32 ipc_dummy_id = -1;
114   const int64 transaction_id = 1;
115   const int64 object_store_id = 2;
116
117   MockCallbacks callbacks;
118   IndexedDBDispatcher dispatcher(thread_safe_sender_.get());
119   dispatcher.RequestIDBDatabasePut(ipc_dummy_id,
120                                    transaction_id,
121                                    object_store_id,
122                                    value,
123                                    web_blob_info,
124                                    key,
125                                    blink::WebIDBPutModeAddOrUpdate,
126                                    &callbacks,
127                                    WebVector<long long>(),
128                                    WebVector<WebVector<WebIDBKey> >());
129
130   EXPECT_TRUE(callbacks.error_seen());
131 }
132
133 namespace {
134
135 class CursorCallbacks : public WebIDBCallbacks {
136  public:
137   explicit CursorCallbacks(scoped_ptr<WebIDBCursor>* cursor)
138       : cursor_(cursor) {}
139
140   virtual void onSuccess(const WebData&,
141                          const WebVector<WebBlobInfo>&) OVERRIDE {}
142   virtual void onSuccess(WebIDBCursor* cursor,
143                          const WebIDBKey& key,
144                          const WebIDBKey& primaryKey,
145                          const WebData& value,
146                          const WebVector<WebBlobInfo>&) OVERRIDE {
147     cursor_->reset(cursor);
148   }
149
150  private:
151   scoped_ptr<WebIDBCursor>* cursor_;
152
153   DISALLOW_COPY_AND_ASSIGN(CursorCallbacks);
154 };
155
156 }  // namespace
157
158 TEST_F(IndexedDBDispatcherTest, CursorTransactionId) {
159   const int32 ipc_database_id = -1;
160   const int64 transaction_id = 1234;
161   const int64 object_store_id = 2;
162   const int32 index_id = 3;
163   const blink::WebIDBCursorDirection direction =
164       blink::WebIDBCursorDirectionNext;
165   const bool key_only = false;
166
167   MockDispatcher dispatcher(thread_safe_sender_.get());
168
169   // First case: successful cursor open.
170   {
171     scoped_ptr<WebIDBCursor> cursor;
172     EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
173
174     // Make a cursor request. This should record the transaction id.
175     dispatcher.RequestIDBDatabaseOpenCursor(ipc_database_id,
176                                             transaction_id,
177                                             object_store_id,
178                                             index_id,
179                                             IndexedDBKeyRange(),
180                                             direction,
181                                             key_only,
182                                             blink::WebIDBTaskTypeNormal,
183                                             new CursorCallbacks(&cursor));
184
185     // Verify that the transaction id was captured.
186     EXPECT_EQ(1UL, dispatcher.cursor_transaction_ids_.size());
187     EXPECT_FALSE(cursor.get());
188
189     int32 ipc_callbacks_id = dispatcher.cursor_transaction_ids_.begin()->first;
190
191     IndexedDBMsg_CallbacksSuccessIDBCursor_Params params;
192     params.ipc_thread_id = dispatcher.CurrentWorkerId();
193     params.ipc_callbacks_id = ipc_callbacks_id;
194
195     // Now simululate the cursor response.
196     params.ipc_cursor_id = WebIDBCursorImpl::kInvalidCursorId;
197     dispatcher.OnSuccessOpenCursor(params);
198
199     EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
200
201     EXPECT_TRUE(cursor.get());
202
203     WebIDBCursorImpl* impl = static_cast<WebIDBCursorImpl*>(cursor.get());
204
205     // This is the primary expectation of this test: the transaction id was
206     // applied to the cursor.
207     EXPECT_EQ(transaction_id, impl->transaction_id());
208   }
209
210   // Second case: null cursor (no data in range)
211   {
212     scoped_ptr<WebIDBCursor> cursor;
213     EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
214
215     // Make a cursor request. This should record the transaction id.
216     dispatcher.RequestIDBDatabaseOpenCursor(ipc_database_id,
217                                             transaction_id,
218                                             object_store_id,
219                                             index_id,
220                                             IndexedDBKeyRange(),
221                                             direction,
222                                             key_only,
223                                             blink::WebIDBTaskTypeNormal,
224                                             new CursorCallbacks(&cursor));
225
226     // Verify that the transaction id was captured.
227     EXPECT_EQ(1UL, dispatcher.cursor_transaction_ids_.size());
228     EXPECT_FALSE(cursor.get());
229
230     int32 ipc_callbacks_id = dispatcher.cursor_transaction_ids_.begin()->first;
231
232     // Now simululate a "null cursor" response.
233     IndexedDBMsg_CallbacksSuccessValue_Params params;
234     params.ipc_thread_id = dispatcher.CurrentWorkerId();
235     params.ipc_callbacks_id = ipc_callbacks_id;
236     dispatcher.OnSuccessValue(params);
237
238     // Ensure the map result was deleted.
239     EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
240     EXPECT_FALSE(cursor.get());
241   }
242 }
243
244 namespace {
245
246 class MockCursor : public WebIDBCursorImpl {
247  public:
248   MockCursor(int32 ipc_cursor_id,
249              int64 transaction_id,
250              ThreadSafeSender* thread_safe_sender)
251       : WebIDBCursorImpl(ipc_cursor_id, transaction_id, thread_safe_sender),
252         reset_count_(0) {}
253
254   // This method is virtual so it can be overridden in unit tests.
255   virtual void ResetPrefetchCache() OVERRIDE { ++reset_count_; }
256
257   int reset_count() const { return reset_count_; }
258
259  private:
260   int reset_count_;
261
262   DISALLOW_COPY_AND_ASSIGN(MockCursor);
263 };
264
265 }  // namespace
266
267 TEST_F(IndexedDBDispatcherTest, CursorReset) {
268   scoped_ptr<WebIDBCursor> cursor;
269   MockDispatcher dispatcher(thread_safe_sender_.get());
270
271   const int32 ipc_database_id = 0;
272   const int32 object_store_id = 0;
273   const int32 index_id = 0;
274   const bool key_only = false;
275   const int cursor1_ipc_id = 1;
276   const int cursor2_ipc_id = 2;
277   const int other_cursor_ipc_id = 2;
278   const int cursor1_transaction_id = 1;
279   const int cursor2_transaction_id = 2;
280   const int other_transaction_id = 3;
281
282   scoped_ptr<MockCursor> cursor1(
283       new MockCursor(WebIDBCursorImpl::kInvalidCursorId,
284                      cursor1_transaction_id,
285                      thread_safe_sender_.get()));
286
287   scoped_ptr<MockCursor> cursor2(
288       new MockCursor(WebIDBCursorImpl::kInvalidCursorId,
289                      cursor2_transaction_id,
290                      thread_safe_sender_.get()));
291
292   dispatcher.cursors_[cursor1_ipc_id] = cursor1.get();
293   dispatcher.cursors_[cursor2_ipc_id] = cursor2.get();
294
295   EXPECT_EQ(0, cursor1->reset_count());
296   EXPECT_EQ(0, cursor2->reset_count());
297
298   // Other transaction:
299   dispatcher.RequestIDBDatabaseGet(ipc_database_id,
300                                    other_transaction_id,
301                                    object_store_id,
302                                    index_id,
303                                    IndexedDBKeyRange(),
304                                    key_only,
305                                    new MockCallbacks());
306
307   EXPECT_EQ(0, cursor1->reset_count());
308   EXPECT_EQ(0, cursor2->reset_count());
309
310   // Same transaction:
311   dispatcher.RequestIDBDatabaseGet(ipc_database_id,
312                                    cursor1_transaction_id,
313                                    object_store_id,
314                                    index_id,
315                                    IndexedDBKeyRange(),
316                                    key_only,
317                                    new MockCallbacks());
318
319   EXPECT_EQ(1, cursor1->reset_count());
320   EXPECT_EQ(0, cursor2->reset_count());
321
322   // Same transaction and same cursor:
323   dispatcher.RequestIDBCursorContinue(IndexedDBKey(),
324                                       IndexedDBKey(),
325                                       new MockCallbacks(),
326                                       cursor1_ipc_id,
327                                       cursor1_transaction_id);
328
329   EXPECT_EQ(1, cursor1->reset_count());
330   EXPECT_EQ(0, cursor2->reset_count());
331
332   // Same transaction and different cursor:
333   dispatcher.RequestIDBCursorContinue(IndexedDBKey(),
334                                       IndexedDBKey(),
335                                       new MockCallbacks(),
336                                       other_cursor_ipc_id,
337                                       cursor1_transaction_id);
338
339   EXPECT_EQ(2, cursor1->reset_count());
340   EXPECT_EQ(0, cursor2->reset_count());
341
342   cursor1.reset();
343   cursor2.reset();
344 }
345
346 }  // namespace content