OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/memory/scoped_ptr.h" | 5 #include "base/memory/scoped_ptr.h" |
6 #include "base/values.h" | 6 #include "base/values.h" |
7 #include "content/child/indexed_db/indexed_db_dispatcher.h" | 7 #include "content/child/indexed_db/indexed_db_dispatcher.h" |
8 #include "content/child/indexed_db/indexed_db_key_builders.h" | 8 #include "content/child/indexed_db/indexed_db_key_builders.h" |
9 #include "content/child/indexed_db/webidbcursor_impl.h" | 9 #include "content/child/indexed_db/webidbcursor_impl.h" |
10 #include "content/child/thread_safe_sender.h" | 10 #include "content/child/thread_safe_sender.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 namespace content { | 23 namespace content { |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 class MockDispatcher : public IndexedDBDispatcher { | 27 class MockDispatcher : public IndexedDBDispatcher { |
28 public: | 28 public: |
29 MockDispatcher(ThreadSafeSender* thread_safe_sender) | 29 MockDispatcher(ThreadSafeSender* thread_safe_sender) |
30 : IndexedDBDispatcher(thread_safe_sender), | 30 : IndexedDBDispatcher(thread_safe_sender), |
31 prefetch_calls_(0), | 31 prefetch_calls_(0), |
32 last_prefetch_count_(0), | 32 last_prefetch_count_(0), |
| 33 advance_calls_(0), |
33 continue_calls_(0), | 34 continue_calls_(0), |
34 destroyed_cursor_id_(0) {} | 35 destroyed_cursor_id_(0) {} |
35 | 36 |
36 virtual void RequestIDBCursorPrefetch(int n, | 37 virtual void RequestIDBCursorPrefetch(int n, |
37 WebIDBCallbacks* callbacks, | 38 WebIDBCallbacks* callbacks, |
38 int32 ipc_cursor_id) OVERRIDE { | 39 int32 ipc_cursor_id) OVERRIDE { |
39 ++prefetch_calls_; | 40 ++prefetch_calls_; |
40 last_prefetch_count_ = n; | 41 last_prefetch_count_ = n; |
41 callbacks_.reset(callbacks); | 42 callbacks_.reset(callbacks); |
42 } | 43 } |
43 | 44 |
| 45 virtual void RequestIDBCursorAdvance(unsigned long count, |
| 46 WebIDBCallbacks* callbacks, |
| 47 int32 ipc_cursor_id) OVERRIDE { |
| 48 ++advance_calls_; |
| 49 callbacks_.reset(callbacks); |
| 50 } |
| 51 |
44 virtual void RequestIDBCursorContinue(const IndexedDBKey& key, | 52 virtual void RequestIDBCursorContinue(const IndexedDBKey& key, |
45 const IndexedDBKey& primary_key, | 53 const IndexedDBKey& primary_key, |
46 WebIDBCallbacks* callbacks, | 54 WebIDBCallbacks* callbacks, |
47 int32 ipc_cursor_id) OVERRIDE { | 55 int32 ipc_cursor_id) OVERRIDE { |
48 ++continue_calls_; | 56 ++continue_calls_; |
49 callbacks_.reset(callbacks); | 57 callbacks_.reset(callbacks); |
50 } | 58 } |
51 | 59 |
52 virtual void CursorDestroyed(int32 ipc_cursor_id) OVERRIDE { | 60 virtual void CursorDestroyed(int32 ipc_cursor_id) OVERRIDE { |
53 destroyed_cursor_id_ = ipc_cursor_id; | 61 destroyed_cursor_id_ = ipc_cursor_id; |
54 } | 62 } |
55 | 63 |
56 int prefetch_calls() { return prefetch_calls_; } | 64 int prefetch_calls() { return prefetch_calls_; } |
| 65 int advance_calls() { return advance_calls_; } |
57 int continue_calls() { return continue_calls_; } | 66 int continue_calls() { return continue_calls_; } |
58 int last_prefetch_count() { return last_prefetch_count_; } | 67 int last_prefetch_count() { return last_prefetch_count_; } |
59 int32 destroyed_cursor_id() { return destroyed_cursor_id_; } | 68 int32 destroyed_cursor_id() { return destroyed_cursor_id_; } |
60 | 69 |
61 private: | 70 private: |
62 int prefetch_calls_; | 71 int prefetch_calls_; |
63 int last_prefetch_count_; | 72 int last_prefetch_count_; |
| 73 int advance_calls_; |
64 int continue_calls_; | 74 int continue_calls_; |
65 int32 destroyed_cursor_id_; | 75 int32 destroyed_cursor_id_; |
66 scoped_ptr<WebIDBCallbacks> callbacks_; | 76 scoped_ptr<WebIDBCallbacks> callbacks_; |
67 }; | 77 }; |
68 | 78 |
69 class MockContinueCallbacks : public WebIDBCallbacks { | 79 class MockContinueCallbacks : public WebIDBCallbacks { |
70 public: | 80 public: |
71 MockContinueCallbacks(IndexedDBKey* key = 0) : key_(key) {} | 81 MockContinueCallbacks(IndexedDBKey* key = 0) : key_(key) {} |
72 | 82 |
73 virtual void onSuccess(const WebIDBKey& key, | 83 virtual void onSuccess(const WebIDBKey& key, |
74 const WebIDBKey& primaryKey, | 84 const WebIDBKey& primaryKey, |
75 const WebData& value) { | 85 const WebData& value) { |
76 | 86 |
77 if (key_) | 87 if (key_) |
78 *key_ = IndexedDBKeyBuilder::Build(key); | 88 *key_ = IndexedDBKeyBuilder::Build(key); |
79 } | 89 } |
80 | 90 |
81 private: | 91 private: |
82 IndexedDBKey* key_; | 92 IndexedDBKey* key_; |
83 }; | 93 }; |
84 | 94 |
85 } // namespace | 95 } // namespace |
86 | 96 |
87 TEST(WebIDBCursorImplTest, PrefetchTest) { | 97 class WebIDBCursorImplTest : public testing::Test { |
| 98 public: |
| 99 WebIDBCursorImplTest() { |
| 100 null_key_.assignNull(); |
| 101 sync_message_filter_ = new IPC::SyncMessageFilter(NULL); |
| 102 thread_safe_sender_ = new ThreadSafeSender( |
| 103 base::MessageLoopProxy::current(), sync_message_filter_.get()); |
| 104 dispatcher_ = |
| 105 make_scoped_ptr(new MockDispatcher(thread_safe_sender_.get())); |
| 106 } |
88 | 107 |
89 WebIDBKey null_key; | 108 protected: |
90 null_key.assignNull(); | 109 WebIDBKey null_key_; |
| 110 scoped_refptr<ThreadSafeSender> thread_safe_sender_; |
| 111 scoped_ptr<MockDispatcher> dispatcher_; |
91 | 112 |
92 scoped_refptr<base::MessageLoopProxy> message_loop_proxy( | 113 private: |
93 base::MessageLoopProxy::current()); | 114 scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_; |
94 scoped_refptr<IPC::SyncMessageFilter> sync_message_filter( | |
95 new IPC::SyncMessageFilter(NULL)); | |
96 scoped_refptr<ThreadSafeSender> thread_safe_sender(new ThreadSafeSender( | |
97 message_loop_proxy.get(), sync_message_filter.get())); | |
98 | 115 |
99 MockDispatcher dispatcher(thread_safe_sender.get()); | 116 DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImplTest); |
| 117 }; |
| 118 |
| 119 TEST_F(WebIDBCursorImplTest, PrefetchTest) { |
100 | 120 |
101 { | 121 { |
102 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId, | 122 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId, |
103 thread_safe_sender.get()); | 123 thread_safe_sender_.get()); |
104 | 124 |
105 // Call continue() until prefetching should kick in. | 125 // Call continue() until prefetching should kick in. |
106 int continue_calls = 0; | 126 int continue_calls = 0; |
107 EXPECT_EQ(dispatcher.continue_calls(), 0); | 127 EXPECT_EQ(dispatcher_->continue_calls(), 0); |
108 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) { | 128 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) { |
109 cursor.continueFunction(null_key, new MockContinueCallbacks()); | 129 cursor.continueFunction(null_key_, new MockContinueCallbacks()); |
110 EXPECT_EQ(++continue_calls, dispatcher.continue_calls()); | 130 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls()); |
111 EXPECT_EQ(0, dispatcher.prefetch_calls()); | 131 EXPECT_EQ(0, dispatcher_->prefetch_calls()); |
112 } | 132 } |
113 | 133 |
114 // Do enough repetitions to verify that the count grows each time, | 134 // Do enough repetitions to verify that the count grows each time, |
115 // but not so many that the maximum limit is hit. | 135 // but not so many that the maximum limit is hit. |
116 const int kPrefetchRepetitions = 5; | 136 const int kPrefetchRepetitions = 5; |
117 | 137 |
118 int expected_key = 0; | 138 int expected_key = 0; |
119 int last_prefetch_count = 0; | 139 int last_prefetch_count = 0; |
120 for (int repetitions = 0; repetitions < kPrefetchRepetitions; | 140 for (int repetitions = 0; repetitions < kPrefetchRepetitions; |
121 ++repetitions) { | 141 ++repetitions) { |
122 | 142 |
123 // Initiate the prefetch | 143 // Initiate the prefetch |
124 cursor.continueFunction(null_key, new MockContinueCallbacks()); | 144 cursor.continueFunction(null_key_, new MockContinueCallbacks()); |
125 EXPECT_EQ(continue_calls, dispatcher.continue_calls()); | 145 EXPECT_EQ(continue_calls, dispatcher_->continue_calls()); |
126 EXPECT_EQ(repetitions + 1, dispatcher.prefetch_calls()); | 146 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls()); |
127 | 147 |
128 // Verify that the requested count has increased since last time. | 148 // Verify that the requested count has increased since last time. |
129 int prefetch_count = dispatcher.last_prefetch_count(); | 149 int prefetch_count = dispatcher_->last_prefetch_count(); |
130 EXPECT_GT(prefetch_count, last_prefetch_count); | 150 EXPECT_GT(prefetch_count, last_prefetch_count); |
131 last_prefetch_count = prefetch_count; | 151 last_prefetch_count = prefetch_count; |
132 | 152 |
133 // Fill the prefetch cache as requested. | 153 // Fill the prefetch cache as requested. |
134 std::vector<IndexedDBKey> keys; | 154 std::vector<IndexedDBKey> keys; |
135 std::vector<IndexedDBKey> primary_keys(prefetch_count); | 155 std::vector<IndexedDBKey> primary_keys(prefetch_count); |
136 std::vector<WebData> values(prefetch_count); | 156 std::vector<WebData> values(prefetch_count); |
137 for (int i = 0; i < prefetch_count; ++i) { | 157 for (int i = 0; i < prefetch_count; ++i) { |
138 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber)); | 158 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber)); |
139 } | 159 } |
140 cursor.SetPrefetchData(keys, primary_keys, values); | 160 cursor.SetPrefetchData(keys, primary_keys, values); |
141 | 161 |
142 // Note that the real dispatcher would call cursor->CachedContinue() | 162 // Note that the real dispatcher would call cursor->CachedContinue() |
143 // immediately after cursor->SetPrefetchData() to service the request | 163 // immediately after cursor->SetPrefetchData() to service the request |
144 // that initiated the prefetch. | 164 // that initiated the prefetch. |
145 | 165 |
146 // Verify that the cache is used for subsequent continue() calls. | 166 // Verify that the cache is used for subsequent continue() calls. |
147 for (int i = 0; i < prefetch_count; ++i) { | 167 for (int i = 0; i < prefetch_count; ++i) { |
148 IndexedDBKey key; | 168 IndexedDBKey key; |
149 cursor.continueFunction(null_key, new MockContinueCallbacks(&key)); | 169 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key)); |
150 EXPECT_EQ(continue_calls, dispatcher.continue_calls()); | 170 EXPECT_EQ(continue_calls, dispatcher_->continue_calls()); |
151 EXPECT_EQ(repetitions + 1, dispatcher.prefetch_calls()); | 171 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls()); |
152 | 172 |
153 EXPECT_EQ(WebIDBKeyTypeNumber, key.type()); | 173 EXPECT_EQ(WebIDBKeyTypeNumber, key.type()); |
154 EXPECT_EQ(expected_key++, key.number()); | 174 EXPECT_EQ(expected_key++, key.number()); |
155 } | 175 } |
156 } | 176 } |
157 } | 177 } |
158 | 178 |
159 EXPECT_EQ(dispatcher.destroyed_cursor_id(), | 179 EXPECT_EQ(dispatcher_->destroyed_cursor_id(), |
160 WebIDBCursorImpl::kInvalidCursorId); | 180 WebIDBCursorImpl::kInvalidCursorId); |
161 } | 181 } |
162 | 182 |
| 183 TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) { |
| 184 |
| 185 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId, |
| 186 thread_safe_sender_.get()); |
| 187 |
| 188 // Call continue() until prefetching should kick in. |
| 189 EXPECT_EQ(0, dispatcher_->continue_calls()); |
| 190 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) { |
| 191 cursor.continueFunction(null_key_, new MockContinueCallbacks()); |
| 192 } |
| 193 EXPECT_EQ(0, dispatcher_->prefetch_calls()); |
| 194 |
| 195 // Initiate the prefetch |
| 196 cursor.continueFunction(null_key_, new MockContinueCallbacks()); |
| 197 |
| 198 EXPECT_EQ(1, dispatcher_->prefetch_calls()); |
| 199 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold), |
| 200 dispatcher_->continue_calls()); |
| 201 EXPECT_EQ(0, dispatcher_->advance_calls()); |
| 202 |
| 203 const int prefetch_count = dispatcher_->last_prefetch_count(); |
| 204 |
| 205 // Fill the prefetch cache as requested. |
| 206 int expected_key = 0; |
| 207 std::vector<IndexedDBKey> keys; |
| 208 std::vector<IndexedDBKey> primary_keys(prefetch_count); |
| 209 std::vector<WebData> values(prefetch_count); |
| 210 for (int i = 0; i < prefetch_count; ++i) { |
| 211 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber)); |
| 212 } |
| 213 cursor.SetPrefetchData(keys, primary_keys, values); |
| 214 |
| 215 // Note that the real dispatcher would call cursor->CachedContinue() |
| 216 // immediately after cursor->SetPrefetchData() to service the request |
| 217 // that initiated the prefetch. |
| 218 |
| 219 // Need at least this many in the cache for the test steps. |
| 220 ASSERT_GE(prefetch_count, 5); |
| 221 |
| 222 // IDBCursor.continue() |
| 223 IndexedDBKey key; |
| 224 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key)); |
| 225 EXPECT_EQ(0, key.number()); |
| 226 |
| 227 // IDBCursor.advance(1) |
| 228 cursor.advance(1, new MockContinueCallbacks(&key)); |
| 229 EXPECT_EQ(1, key.number()); |
| 230 |
| 231 // IDBCursor.continue() |
| 232 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key)); |
| 233 EXPECT_EQ(2, key.number()); |
| 234 |
| 235 // IDBCursor.advance(2) |
| 236 cursor.advance(2, new MockContinueCallbacks(&key)); |
| 237 EXPECT_EQ(4, key.number()); |
| 238 |
| 239 EXPECT_EQ(0, dispatcher_->advance_calls()); |
| 240 |
| 241 // IDBCursor.advance(lots) - beyond the fetched amount |
| 242 cursor.advance(WebIDBCursorImpl::kMaxPrefetchAmount, |
| 243 new MockContinueCallbacks(&key)); |
| 244 EXPECT_EQ(1, dispatcher_->advance_calls()); |
| 245 EXPECT_EQ(1, dispatcher_->prefetch_calls()); |
| 246 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold), |
| 247 dispatcher_->continue_calls()); |
| 248 } |
| 249 |
163 } // namespace content | 250 } // namespace content |
OLD | NEW |