| 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/proxy_webidbcursor_impl.h" | 9 #include "content/child/indexed_db/proxy_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(RendererWebIDBCursorImplTest, PrefetchTest) { | 97 class RendererWebIDBCursorImplTest : public testing::Test { |
| 98 public: |
| 99 RendererWebIDBCursorImplTest() { |
| 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(RendererWebIDBCursorImplTest); |
| 117 }; |
| 118 |
| 119 TEST_F(RendererWebIDBCursorImplTest, PrefetchTest) { |
| 100 | 120 |
| 101 { | 121 { |
| 102 RendererWebIDBCursorImpl cursor(RendererWebIDBCursorImpl::kInvalidCursorId, | 122 RendererWebIDBCursorImpl cursor(RendererWebIDBCursorImpl::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 < RendererWebIDBCursorImpl::kPrefetchContinueThreshold; | 128 for (int i = 0; i < RendererWebIDBCursorImpl::kPrefetchContinueThreshold; |
| 109 ++i) { | 129 ++i) { |
| 110 cursor.continueFunction(null_key, new MockContinueCallbacks()); | 130 cursor.continueFunction(null_key_, new MockContinueCallbacks()); |
| 111 EXPECT_EQ(++continue_calls, dispatcher.continue_calls()); | 131 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls()); |
| 112 EXPECT_EQ(0, dispatcher.prefetch_calls()); | 132 EXPECT_EQ(0, dispatcher_->prefetch_calls()); |
| 113 } | 133 } |
| 114 | 134 |
| 115 // Do enough repetitions to verify that the count grows each time, | 135 // Do enough repetitions to verify that the count grows each time, |
| 116 // but not so many that the maximum limit is hit. | 136 // but not so many that the maximum limit is hit. |
| 117 const int kPrefetchRepetitions = 5; | 137 const int kPrefetchRepetitions = 5; |
| 118 | 138 |
| 119 int expected_key = 0; | 139 int expected_key = 0; |
| 120 int last_prefetch_count = 0; | 140 int last_prefetch_count = 0; |
| 121 for (int repetitions = 0; repetitions < kPrefetchRepetitions; | 141 for (int repetitions = 0; repetitions < kPrefetchRepetitions; |
| 122 ++repetitions) { | 142 ++repetitions) { |
| 123 | 143 |
| 124 // Initiate the prefetch | 144 // Initiate the prefetch |
| 125 cursor.continueFunction(null_key, new MockContinueCallbacks()); | 145 cursor.continueFunction(null_key_, new MockContinueCallbacks()); |
| 126 EXPECT_EQ(continue_calls, dispatcher.continue_calls()); | 146 EXPECT_EQ(continue_calls, dispatcher_->continue_calls()); |
| 127 EXPECT_EQ(repetitions + 1, dispatcher.prefetch_calls()); | 147 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls()); |
| 128 | 148 |
| 129 // Verify that the requested count has increased since last time. | 149 // Verify that the requested count has increased since last time. |
| 130 int prefetch_count = dispatcher.last_prefetch_count(); | 150 int prefetch_count = dispatcher_->last_prefetch_count(); |
| 131 EXPECT_GT(prefetch_count, last_prefetch_count); | 151 EXPECT_GT(prefetch_count, last_prefetch_count); |
| 132 last_prefetch_count = prefetch_count; | 152 last_prefetch_count = prefetch_count; |
| 133 | 153 |
| 134 // Fill the prefetch cache as requested. | 154 // Fill the prefetch cache as requested. |
| 135 std::vector<IndexedDBKey> keys; | 155 std::vector<IndexedDBKey> keys; |
| 136 std::vector<IndexedDBKey> primary_keys(prefetch_count); | 156 std::vector<IndexedDBKey> primary_keys(prefetch_count); |
| 137 std::vector<WebData> values(prefetch_count); | 157 std::vector<WebData> values(prefetch_count); |
| 138 for (int i = 0; i < prefetch_count; ++i) { | 158 for (int i = 0; i < prefetch_count; ++i) { |
| 139 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber)); | 159 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber)); |
| 140 } | 160 } |
| 141 cursor.SetPrefetchData(keys, primary_keys, values); | 161 cursor.SetPrefetchData(keys, primary_keys, values); |
| 142 | 162 |
| 143 // Note that the real dispatcher would call cursor->CachedContinue() | 163 // Note that the real dispatcher would call cursor->CachedContinue() |
| 144 // immediately after cursor->SetPrefetchData() to service the request | 164 // immediately after cursor->SetPrefetchData() to service the request |
| 145 // that initiated the prefetch. | 165 // that initiated the prefetch. |
| 146 | 166 |
| 147 // Verify that the cache is used for subsequent continue() calls. | 167 // Verify that the cache is used for subsequent continue() calls. |
| 148 for (int i = 0; i < prefetch_count; ++i) { | 168 for (int i = 0; i < prefetch_count; ++i) { |
| 149 IndexedDBKey key; | 169 IndexedDBKey key; |
| 150 cursor.continueFunction(null_key, new MockContinueCallbacks(&key)); | 170 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key)); |
| 151 EXPECT_EQ(continue_calls, dispatcher.continue_calls()); | 171 EXPECT_EQ(continue_calls, dispatcher_->continue_calls()); |
| 152 EXPECT_EQ(repetitions + 1, dispatcher.prefetch_calls()); | 172 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls()); |
| 153 | 173 |
| 154 EXPECT_EQ(WebIDBKeyTypeNumber, key.type()); | 174 EXPECT_EQ(WebIDBKeyTypeNumber, key.type()); |
| 155 EXPECT_EQ(expected_key++, key.number()); | 175 EXPECT_EQ(expected_key++, key.number()); |
| 156 } | 176 } |
| 157 } | 177 } |
| 158 } | 178 } |
| 159 | 179 |
| 160 EXPECT_EQ(dispatcher.destroyed_cursor_id(), | 180 EXPECT_EQ(dispatcher_->destroyed_cursor_id(), |
| 161 RendererWebIDBCursorImpl::kInvalidCursorId); | 181 RendererWebIDBCursorImpl::kInvalidCursorId); |
| 162 } | 182 } |
| 163 | 183 |
| 184 TEST_F(RendererWebIDBCursorImplTest, AdvancePrefetchTest) { |
| 185 |
| 186 RendererWebIDBCursorImpl cursor(RendererWebIDBCursorImpl::kInvalidCursorId, |
| 187 thread_safe_sender_.get()); |
| 188 |
| 189 // Call continue() until prefetching should kick in. |
| 190 EXPECT_EQ(0, dispatcher_->continue_calls()); |
| 191 for (int i = 0; i < RendererWebIDBCursorImpl::kPrefetchContinueThreshold; |
| 192 ++i) { |
| 193 cursor.continueFunction(null_key_, new MockContinueCallbacks()); |
| 194 } |
| 195 EXPECT_EQ(0, dispatcher_->prefetch_calls()); |
| 196 |
| 197 // Initiate the prefetch |
| 198 cursor.continueFunction(null_key_, new MockContinueCallbacks()); |
| 199 |
| 200 EXPECT_EQ(1, dispatcher_->prefetch_calls()); |
| 201 EXPECT_EQ(RendererWebIDBCursorImpl::kPrefetchContinueThreshold, |
| 202 dispatcher_->continue_calls()); |
| 203 EXPECT_EQ(0, dispatcher_->advance_calls()); |
| 204 |
| 205 const int prefetch_count = dispatcher_->last_prefetch_count(); |
| 206 |
| 207 // Fill the prefetch cache as requested. |
| 208 int expected_key = 0; |
| 209 std::vector<IndexedDBKey> keys; |
| 210 std::vector<IndexedDBKey> primary_keys(prefetch_count); |
| 211 std::vector<WebData> values(prefetch_count); |
| 212 for (int i = 0; i < prefetch_count; ++i) { |
| 213 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber)); |
| 214 } |
| 215 cursor.SetPrefetchData(keys, primary_keys, values); |
| 216 |
| 217 // Note that the real dispatcher would call cursor->CachedContinue() |
| 218 // immediately after cursor->SetPrefetchData() to service the request |
| 219 // that initiated the prefetch. |
| 220 |
| 221 // Need at least this many in the cache for the test steps. |
| 222 ASSERT_GE(prefetch_count, 5); |
| 223 |
| 224 // IDBCursor.continue() |
| 225 IndexedDBKey key; |
| 226 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key)); |
| 227 EXPECT_EQ(0, key.number()); |
| 228 |
| 229 // IDBCursor.advance(1) |
| 230 cursor.advance(1, new MockContinueCallbacks(&key)); |
| 231 EXPECT_EQ(1, key.number()); |
| 232 |
| 233 // IDBCursor.continue() |
| 234 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key)); |
| 235 EXPECT_EQ(2, key.number()); |
| 236 |
| 237 // IDBCursor.advance(2) |
| 238 cursor.advance(2, new MockContinueCallbacks(&key)); |
| 239 EXPECT_EQ(4, key.number()); |
| 240 |
| 241 EXPECT_EQ(0, dispatcher_->advance_calls()); |
| 242 |
| 243 // IDBCursor.advance(lots) - beyond the fetched amount |
| 244 cursor.advance(RendererWebIDBCursorImpl::kMaxPrefetchAmount, |
| 245 new MockContinueCallbacks(&key)); |
| 246 EXPECT_EQ(1, dispatcher_->advance_calls()); |
| 247 EXPECT_EQ(1, dispatcher_->prefetch_calls()); |
| 248 EXPECT_EQ(RendererWebIDBCursorImpl::kPrefetchContinueThreshold, |
| 249 dispatcher_->continue_calls()); |
| 250 } |
| 251 |
| 164 } // namespace content | 252 } // namespace content |
| OLD | NEW |