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