| 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 "content/child/indexed_db/webidbcursor_impl.h" | 5 #include "content/child/indexed_db/webidbcursor_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| 11 | 11 |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/run_loop.h" |
| 14 #include "base/threading/thread_task_runner_handle.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
| 15 #include "base/values.h" | 16 #include "base/values.h" |
| 16 #include "content/child/indexed_db/indexed_db_dispatcher.h" | |
| 17 #include "content/child/indexed_db/indexed_db_key_builders.h" | 17 #include "content/child/indexed_db/indexed_db_key_builders.h" |
| 18 #include "content/child/indexed_db/mock_webidbcallbacks.h" | 18 #include "content/child/indexed_db/mock_webidbcallbacks.h" |
| 19 #include "content/child/thread_safe_sender.h" | 19 #include "content/child/thread_safe_sender.h" |
| 20 #include "content/common/indexed_db/indexed_db_key.h" | 20 #include "content/common/indexed_db/indexed_db_key.h" |
| 21 #include "ipc/ipc_sync_message_filter.h" | 21 #include "mojo/public/cpp/bindings/associated_binding.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
| 23 #include "third_party/WebKit/public/platform/WebData.h" | 23 #include "third_party/WebKit/public/platform/WebData.h" |
| 24 | 24 |
| 25 using blink::WebBlobInfo; | 25 using blink::WebBlobInfo; |
| 26 using blink::WebData; | 26 using blink::WebData; |
| 27 using blink::WebIDBCallbacks; | 27 using blink::WebIDBCallbacks; |
| 28 using blink::WebIDBKey; | 28 using blink::WebIDBKey; |
| 29 using blink::WebIDBKeyTypeNumber; | 29 using blink::WebIDBKeyTypeNumber; |
| 30 using blink::WebIDBValue; | 30 using blink::WebIDBValue; |
| 31 using blink::WebVector; | 31 using blink::WebVector; |
| 32 using indexed_db::mojom::Cursor; |
| 32 using testing::StrictMock; | 33 using testing::StrictMock; |
| 33 | 34 |
| 34 namespace content { | 35 namespace content { |
| 35 | 36 |
| 36 namespace { | 37 namespace { |
| 37 | 38 |
| 38 class MockDispatcher : public IndexedDBDispatcher { | 39 class MockCursorImpl : public Cursor { |
| 39 public: | 40 public: |
| 40 explicit MockDispatcher(ThreadSafeSender* thread_safe_sender) | 41 explicit MockCursorImpl(indexed_db::mojom::CursorAssociatedRequest request) |
| 41 : IndexedDBDispatcher(thread_safe_sender), | 42 : binding_(this, std::move(request)) { |
| 42 prefetch_calls_(0), | 43 binding_.set_connection_error_handler( |
| 43 last_prefetch_count_(0), | 44 base::Bind(&MockCursorImpl::CursorDestroyed, base::Unretained(this))); |
| 44 reset_calls_(0), | |
| 45 last_used_count_(0), | |
| 46 advance_calls_(0), | |
| 47 continue_calls_(0), | |
| 48 destroyed_cursor_id_(0) {} | |
| 49 | |
| 50 void RequestIDBCursorPrefetch(int n, | |
| 51 WebIDBCallbacks* callbacks, | |
| 52 int32_t ipc_cursor_id) override { | |
| 53 ++prefetch_calls_; | |
| 54 last_prefetch_count_ = n; | |
| 55 callbacks_.reset(callbacks); | |
| 56 } | 45 } |
| 57 | 46 |
| 58 void RequestIDBCursorPrefetchReset(int used_prefetches, | 47 void Prefetch( |
| 59 int unused_prefetches, | 48 int32_t count, |
| 60 int32_t ipc_cursor_id) override { | 49 ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override { |
| 50 ++prefetch_calls_; |
| 51 last_prefetch_count_ = count; |
| 52 } |
| 53 |
| 54 void PrefetchReset( |
| 55 int32_t used_prefetches, |
| 56 int32_t unused_prefetches, |
| 57 const std::vector<std::string>& unused_blob_uuids) override { |
| 61 ++reset_calls_; | 58 ++reset_calls_; |
| 62 last_used_count_ = used_prefetches; | 59 last_used_count_ = used_prefetches; |
| 63 } | 60 } |
| 64 | 61 |
| 65 void RequestIDBCursorAdvance(unsigned long count, | 62 void Advance( |
| 66 WebIDBCallbacks* callbacks, | 63 uint32_t count, |
| 67 int32_t ipc_cursor_id, | 64 ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override { |
| 68 int64_t transaction_id) override { | |
| 69 ++advance_calls_; | 65 ++advance_calls_; |
| 70 callbacks_.reset(callbacks); | |
| 71 } | 66 } |
| 72 | 67 |
| 73 void RequestIDBCursorContinue(const IndexedDBKey& key, | 68 void Continue( |
| 74 const IndexedDBKey& primary_key, | 69 const IndexedDBKey& key, |
| 75 WebIDBCallbacks* callbacks, | 70 const IndexedDBKey& primary_key, |
| 76 int32_t ipc_cursor_id, | 71 ::indexed_db::mojom::CallbacksAssociatedPtrInfo callbacks) override { |
| 77 int64_t transaction_id) override { | |
| 78 ++continue_calls_; | 72 ++continue_calls_; |
| 79 callbacks_.reset(callbacks); | |
| 80 } | 73 } |
| 81 | 74 |
| 82 void CursorDestroyed(int32_t ipc_cursor_id) override { | 75 void CursorDestroyed() { destroyed_ = true; } |
| 83 destroyed_cursor_id_ = ipc_cursor_id; | |
| 84 } | |
| 85 | 76 |
| 86 int prefetch_calls() { return prefetch_calls_; } | 77 int prefetch_calls() { return prefetch_calls_; } |
| 87 int last_prefetch_count() { return last_prefetch_count_; } | 78 int last_prefetch_count() { return last_prefetch_count_; } |
| 88 int reset_calls() { return reset_calls_; } | 79 int reset_calls() { return reset_calls_; } |
| 89 int last_used_count() { return last_used_count_; } | 80 int last_used_count() { return last_used_count_; } |
| 90 int advance_calls() { return advance_calls_; } | 81 int advance_calls() { return advance_calls_; } |
| 91 int continue_calls() { return continue_calls_; } | 82 int continue_calls() { return continue_calls_; } |
| 92 int32_t destroyed_cursor_id() { return destroyed_cursor_id_; } | 83 bool destroyed() { return destroyed_; } |
| 93 | 84 |
| 94 private: | 85 private: |
| 95 int prefetch_calls_; | 86 int prefetch_calls_ = 0; |
| 96 int last_prefetch_count_; | 87 int last_prefetch_count_ = 0; |
| 97 int reset_calls_; | 88 int reset_calls_ = 0; |
| 98 int last_used_count_; | 89 int last_used_count_ = 0; |
| 99 int advance_calls_; | 90 int advance_calls_ = 0; |
| 100 int continue_calls_; | 91 int continue_calls_ = 0; |
| 101 int32_t destroyed_cursor_id_; | 92 bool destroyed_ = false; |
| 102 std::unique_ptr<WebIDBCallbacks> callbacks_; | 93 |
| 94 mojo::AssociatedBinding<Cursor> binding_; |
| 103 }; | 95 }; |
| 104 | 96 |
| 105 class MockContinueCallbacks : public StrictMock<MockWebIDBCallbacks> { | 97 class MockContinueCallbacks : public StrictMock<MockWebIDBCallbacks> { |
| 106 public: | 98 public: |
| 107 MockContinueCallbacks(IndexedDBKey* key = 0, | 99 MockContinueCallbacks(IndexedDBKey* key = 0, |
| 108 WebVector<WebBlobInfo>* webBlobInfo = 0) | 100 WebVector<WebBlobInfo>* webBlobInfo = 0) |
| 109 : key_(key), web_blob_info_(webBlobInfo) {} | 101 : key_(key), web_blob_info_(webBlobInfo) {} |
| 110 | 102 |
| 111 void onSuccess(const WebIDBKey& key, | 103 void onSuccess(const WebIDBKey& key, |
| 112 const WebIDBKey& primaryKey, | 104 const WebIDBKey& primaryKey, |
| 113 const WebIDBValue& value) override { | 105 const WebIDBValue& value) override { |
| 114 if (key_) | 106 if (key_) |
| 115 *key_ = IndexedDBKeyBuilder::Build(key); | 107 *key_ = IndexedDBKeyBuilder::Build(key); |
| 116 if (web_blob_info_) | 108 if (web_blob_info_) |
| 117 *web_blob_info_ = value.webBlobInfo; | 109 *web_blob_info_ = value.webBlobInfo; |
| 118 } | 110 } |
| 119 | 111 |
| 120 private: | 112 private: |
| 121 IndexedDBKey* key_; | 113 IndexedDBKey* key_; |
| 122 WebVector<WebBlobInfo>* web_blob_info_; | 114 WebVector<WebBlobInfo>* web_blob_info_; |
| 123 }; | 115 }; |
| 124 | 116 |
| 125 class MockSyncMessageFilter : public IPC::SyncMessageFilter { | |
| 126 public: | |
| 127 MockSyncMessageFilter() : SyncMessageFilter(nullptr) {} | |
| 128 | |
| 129 private: | |
| 130 ~MockSyncMessageFilter() override {} | |
| 131 }; | |
| 132 | |
| 133 } // namespace | 117 } // namespace |
| 134 | 118 |
| 135 class WebIDBCursorImplTest : public testing::Test { | 119 class WebIDBCursorImplTest : public testing::Test { |
| 136 public: | 120 public: |
| 137 WebIDBCursorImplTest() { | 121 WebIDBCursorImplTest() { |
| 138 null_key_.assignNull(); | 122 null_key_.assignNull(); |
| 139 thread_safe_sender_ = new ThreadSafeSender( | 123 indexed_db::mojom::CursorAssociatedPtr ptr; |
| 140 base::ThreadTaskRunnerHandle::Get(), new MockSyncMessageFilter); | 124 mock_cursor_ = |
| 141 dispatcher_ = base::MakeUnique<MockDispatcher>(thread_safe_sender_.get()); | 125 base::MakeUnique<MockCursorImpl>(mojo::GetProxyForTesting(&ptr)); |
| 126 cursor_ = base::MakeUnique<WebIDBCursorImpl>( |
| 127 ptr.PassInterface(), 1, base::ThreadTaskRunnerHandle::Get()); |
| 142 } | 128 } |
| 143 | 129 |
| 144 protected: | 130 protected: |
| 145 base::MessageLoop message_loop_; | 131 base::MessageLoop message_loop_; |
| 146 WebIDBKey null_key_; | 132 WebIDBKey null_key_; |
| 147 scoped_refptr<ThreadSafeSender> thread_safe_sender_; | 133 std::unique_ptr<WebIDBCursorImpl> cursor_; |
| 148 std::unique_ptr<MockDispatcher> dispatcher_; | 134 std::unique_ptr<MockCursorImpl> mock_cursor_; |
| 149 | 135 |
| 150 private: | 136 private: |
| 151 DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImplTest); | 137 DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImplTest); |
| 152 }; | 138 }; |
| 153 | 139 |
| 154 TEST_F(WebIDBCursorImplTest, PrefetchTest) { | 140 TEST_F(WebIDBCursorImplTest, PrefetchTest) { |
| 155 const int64_t transaction_id = 1; | 141 // Call continue() until prefetching should kick in. |
| 156 { | 142 int continue_calls = 0; |
| 157 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId, | 143 EXPECT_EQ(mock_cursor_->continue_calls(), 0); |
| 158 transaction_id, | 144 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) { |
| 159 thread_safe_sender_.get()); | 145 cursor_->continueFunction(null_key_, new MockContinueCallbacks()); |
| 146 base::RunLoop().RunUntilIdle(); |
| 147 EXPECT_EQ(++continue_calls, mock_cursor_->continue_calls()); |
| 148 EXPECT_EQ(0, mock_cursor_->prefetch_calls()); |
| 149 } |
| 160 | 150 |
| 161 // Call continue() until prefetching should kick in. | 151 // Do enough repetitions to verify that the count grows each time, |
| 162 int continue_calls = 0; | 152 // but not so many that the maximum limit is hit. |
| 163 EXPECT_EQ(dispatcher_->continue_calls(), 0); | 153 const int kPrefetchRepetitions = 5; |
| 164 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) { | 154 |
| 165 cursor.continueFunction(null_key_, new MockContinueCallbacks()); | 155 int expected_key = 0; |
| 166 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls()); | 156 int last_prefetch_count = 0; |
| 167 EXPECT_EQ(0, dispatcher_->prefetch_calls()); | 157 for (int repetitions = 0; repetitions < kPrefetchRepetitions; ++repetitions) { |
| 158 // Initiate the prefetch |
| 159 cursor_->continueFunction(null_key_, new MockContinueCallbacks()); |
| 160 base::RunLoop().RunUntilIdle(); |
| 161 EXPECT_EQ(continue_calls, mock_cursor_->continue_calls()); |
| 162 EXPECT_EQ(repetitions + 1, mock_cursor_->prefetch_calls()); |
| 163 |
| 164 // Verify that the requested count has increased since last time. |
| 165 int prefetch_count = mock_cursor_->last_prefetch_count(); |
| 166 EXPECT_GT(prefetch_count, last_prefetch_count); |
| 167 last_prefetch_count = prefetch_count; |
| 168 |
| 169 // Fill the prefetch cache as requested. |
| 170 std::vector<IndexedDBKey> keys; |
| 171 std::vector<IndexedDBKey> primary_keys(prefetch_count); |
| 172 std::vector<WebIDBValue> values(prefetch_count); |
| 173 for (int i = 0; i < prefetch_count; ++i) { |
| 174 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber)); |
| 175 values[i].webBlobInfo = |
| 176 WebVector<WebBlobInfo>(static_cast<size_t>(expected_key + i)); |
| 168 } | 177 } |
| 178 cursor_->SetPrefetchData(keys, primary_keys, values); |
| 169 | 179 |
| 170 // Do enough repetitions to verify that the count grows each time, | 180 // Note that the real dispatcher would call cursor->CachedContinue() |
| 171 // but not so many that the maximum limit is hit. | 181 // immediately after cursor->SetPrefetchData() to service the request |
| 172 const int kPrefetchRepetitions = 5; | 182 // that initiated the prefetch. |
| 173 | 183 |
| 174 int expected_key = 0; | 184 // Verify that the cache is used for subsequent continue() calls. |
| 175 int last_prefetch_count = 0; | 185 for (int i = 0; i < prefetch_count; ++i) { |
| 176 for (int repetitions = 0; repetitions < kPrefetchRepetitions; | 186 IndexedDBKey key; |
| 177 ++repetitions) { | 187 WebVector<WebBlobInfo> web_blob_info; |
| 178 // Initiate the prefetch | 188 cursor_->continueFunction( |
| 179 cursor.continueFunction(null_key_, new MockContinueCallbacks()); | 189 null_key_, new MockContinueCallbacks(&key, &web_blob_info)); |
| 180 EXPECT_EQ(continue_calls, dispatcher_->continue_calls()); | 190 base::RunLoop().RunUntilIdle(); |
| 181 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls()); | 191 EXPECT_EQ(continue_calls, mock_cursor_->continue_calls()); |
| 192 EXPECT_EQ(repetitions + 1, mock_cursor_->prefetch_calls()); |
| 182 | 193 |
| 183 // Verify that the requested count has increased since last time. | 194 EXPECT_EQ(WebIDBKeyTypeNumber, key.type()); |
| 184 int prefetch_count = dispatcher_->last_prefetch_count(); | 195 EXPECT_EQ(expected_key, static_cast<int>(web_blob_info.size())); |
| 185 EXPECT_GT(prefetch_count, last_prefetch_count); | 196 EXPECT_EQ(expected_key++, key.number()); |
| 186 last_prefetch_count = prefetch_count; | |
| 187 | |
| 188 // Fill the prefetch cache as requested. | |
| 189 std::vector<IndexedDBKey> keys; | |
| 190 std::vector<IndexedDBKey> primary_keys(prefetch_count); | |
| 191 std::vector<WebIDBValue> values(prefetch_count); | |
| 192 for (int i = 0; i < prefetch_count; ++i) { | |
| 193 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber)); | |
| 194 values[i].webBlobInfo = | |
| 195 WebVector<WebBlobInfo>(static_cast<size_t>(expected_key + i)); | |
| 196 } | |
| 197 cursor.SetPrefetchData(keys, primary_keys, values); | |
| 198 | |
| 199 // Note that the real dispatcher would call cursor->CachedContinue() | |
| 200 // immediately after cursor->SetPrefetchData() to service the request | |
| 201 // that initiated the prefetch. | |
| 202 | |
| 203 // Verify that the cache is used for subsequent continue() calls. | |
| 204 for (int i = 0; i < prefetch_count; ++i) { | |
| 205 IndexedDBKey key; | |
| 206 WebVector<WebBlobInfo> web_blob_info; | |
| 207 cursor.continueFunction( | |
| 208 null_key_, new MockContinueCallbacks(&key, &web_blob_info)); | |
| 209 EXPECT_EQ(continue_calls, dispatcher_->continue_calls()); | |
| 210 EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls()); | |
| 211 | |
| 212 EXPECT_EQ(WebIDBKeyTypeNumber, key.type()); | |
| 213 EXPECT_EQ(expected_key, static_cast<int>(web_blob_info.size())); | |
| 214 EXPECT_EQ(expected_key++, key.number()); | |
| 215 } | |
| 216 } | 197 } |
| 217 } | 198 } |
| 218 | 199 |
| 219 EXPECT_EQ(dispatcher_->destroyed_cursor_id(), | 200 cursor_.reset(); |
| 220 WebIDBCursorImpl::kInvalidCursorId); | 201 base::RunLoop().RunUntilIdle(); |
| 202 EXPECT_TRUE(mock_cursor_->destroyed()); |
| 221 } | 203 } |
| 222 | 204 |
| 223 TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) { | 205 TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) { |
| 224 const int64_t transaction_id = 1; | |
| 225 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId, | |
| 226 transaction_id, | |
| 227 thread_safe_sender_.get()); | |
| 228 | |
| 229 // Call continue() until prefetching should kick in. | 206 // Call continue() until prefetching should kick in. |
| 230 EXPECT_EQ(0, dispatcher_->continue_calls()); | 207 EXPECT_EQ(0, mock_cursor_->continue_calls()); |
| 231 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) { | 208 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) { |
| 232 cursor.continueFunction(null_key_, new MockContinueCallbacks()); | 209 cursor_->continueFunction(null_key_, new MockContinueCallbacks()); |
| 233 } | 210 } |
| 234 EXPECT_EQ(0, dispatcher_->prefetch_calls()); | 211 base::RunLoop().RunUntilIdle(); |
| 212 EXPECT_EQ(0, mock_cursor_->prefetch_calls()); |
| 235 | 213 |
| 236 // Initiate the prefetch | 214 // Initiate the prefetch |
| 237 cursor.continueFunction(null_key_, new MockContinueCallbacks()); | 215 cursor_->continueFunction(null_key_, new MockContinueCallbacks()); |
| 238 | 216 |
| 239 EXPECT_EQ(1, dispatcher_->prefetch_calls()); | 217 base::RunLoop().RunUntilIdle(); |
| 218 EXPECT_EQ(1, mock_cursor_->prefetch_calls()); |
| 240 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold), | 219 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold), |
| 241 dispatcher_->continue_calls()); | 220 mock_cursor_->continue_calls()); |
| 242 EXPECT_EQ(0, dispatcher_->advance_calls()); | 221 EXPECT_EQ(0, mock_cursor_->advance_calls()); |
| 243 | 222 |
| 244 const int prefetch_count = dispatcher_->last_prefetch_count(); | 223 const int prefetch_count = mock_cursor_->last_prefetch_count(); |
| 245 | 224 |
| 246 // Fill the prefetch cache as requested. | 225 // Fill the prefetch cache as requested. |
| 247 int expected_key = 0; | 226 int expected_key = 0; |
| 248 std::vector<IndexedDBKey> keys; | 227 std::vector<IndexedDBKey> keys; |
| 249 std::vector<IndexedDBKey> primary_keys(prefetch_count); | 228 std::vector<IndexedDBKey> primary_keys(prefetch_count); |
| 250 std::vector<WebIDBValue> values(prefetch_count); | 229 std::vector<WebIDBValue> values(prefetch_count); |
| 251 for (int i = 0; i < prefetch_count; ++i) { | 230 for (int i = 0; i < prefetch_count; ++i) { |
| 252 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber)); | 231 keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber)); |
| 253 values[i].webBlobInfo = | 232 values[i].webBlobInfo = |
| 254 WebVector<WebBlobInfo>(static_cast<size_t>(expected_key + i)); | 233 WebVector<WebBlobInfo>(static_cast<size_t>(expected_key + i)); |
| 255 } | 234 } |
| 256 cursor.SetPrefetchData(keys, primary_keys, values); | 235 cursor_->SetPrefetchData(keys, primary_keys, values); |
| 257 | 236 |
| 258 // Note that the real dispatcher would call cursor->CachedContinue() | 237 // Note that the real dispatcher would call cursor->CachedContinue() |
| 259 // immediately after cursor->SetPrefetchData() to service the request | 238 // immediately after cursor->SetPrefetchData() to service the request |
| 260 // that initiated the prefetch. | 239 // that initiated the prefetch. |
| 261 | 240 |
| 262 // Need at least this many in the cache for the test steps. | 241 // Need at least this many in the cache for the test steps. |
| 263 ASSERT_GE(prefetch_count, 5); | 242 ASSERT_GE(prefetch_count, 5); |
| 264 | 243 |
| 265 // IDBCursor.continue() | 244 // IDBCursor.continue() |
| 266 IndexedDBKey key; | 245 IndexedDBKey key; |
| 267 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key)); | 246 cursor_->continueFunction(null_key_, new MockContinueCallbacks(&key)); |
| 247 base::RunLoop().RunUntilIdle(); |
| 268 EXPECT_EQ(0, key.number()); | 248 EXPECT_EQ(0, key.number()); |
| 269 | 249 |
| 270 // IDBCursor.advance(1) | 250 // IDBCursor.advance(1) |
| 271 cursor.advance(1, new MockContinueCallbacks(&key)); | 251 cursor_->advance(1, new MockContinueCallbacks(&key)); |
| 252 base::RunLoop().RunUntilIdle(); |
| 272 EXPECT_EQ(1, key.number()); | 253 EXPECT_EQ(1, key.number()); |
| 273 | 254 |
| 274 // IDBCursor.continue() | 255 // IDBCursor.continue() |
| 275 cursor.continueFunction(null_key_, new MockContinueCallbacks(&key)); | 256 cursor_->continueFunction(null_key_, new MockContinueCallbacks(&key)); |
| 257 base::RunLoop().RunUntilIdle(); |
| 276 EXPECT_EQ(2, key.number()); | 258 EXPECT_EQ(2, key.number()); |
| 277 | 259 |
| 278 // IDBCursor.advance(2) | 260 // IDBCursor.advance(2) |
| 279 cursor.advance(2, new MockContinueCallbacks(&key)); | 261 cursor_->advance(2, new MockContinueCallbacks(&key)); |
| 262 base::RunLoop().RunUntilIdle(); |
| 280 EXPECT_EQ(4, key.number()); | 263 EXPECT_EQ(4, key.number()); |
| 281 | 264 |
| 282 EXPECT_EQ(0, dispatcher_->advance_calls()); | 265 EXPECT_EQ(0, mock_cursor_->advance_calls()); |
| 283 | 266 |
| 284 // IDBCursor.advance(lots) - beyond the fetched amount | 267 // IDBCursor.advance(lots) - beyond the fetched amount |
| 285 cursor.advance(WebIDBCursorImpl::kMaxPrefetchAmount, | 268 cursor_->advance(WebIDBCursorImpl::kMaxPrefetchAmount, |
| 286 new MockContinueCallbacks(&key)); | 269 new MockContinueCallbacks(&key)); |
| 287 EXPECT_EQ(1, dispatcher_->advance_calls()); | 270 base::RunLoop().RunUntilIdle(); |
| 288 EXPECT_EQ(1, dispatcher_->prefetch_calls()); | 271 EXPECT_EQ(1, mock_cursor_->advance_calls()); |
| 272 EXPECT_EQ(1, mock_cursor_->prefetch_calls()); |
| 289 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold), | 273 EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold), |
| 290 dispatcher_->continue_calls()); | 274 mock_cursor_->continue_calls()); |
| 275 |
| 276 cursor_.reset(); |
| 277 base::RunLoop().RunUntilIdle(); |
| 278 EXPECT_TRUE(mock_cursor_->destroyed()); |
| 291 } | 279 } |
| 292 | 280 |
| 293 TEST_F(WebIDBCursorImplTest, PrefetchReset) { | 281 TEST_F(WebIDBCursorImplTest, PrefetchReset) { |
| 294 const int64_t transaction_id = 1; | |
| 295 WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId, | |
| 296 transaction_id, | |
| 297 thread_safe_sender_.get()); | |
| 298 | |
| 299 // Call continue() until prefetching should kick in. | 282 // Call continue() until prefetching should kick in. |
| 300 int continue_calls = 0; | 283 int continue_calls = 0; |
| 301 EXPECT_EQ(dispatcher_->continue_calls(), 0); | 284 EXPECT_EQ(mock_cursor_->continue_calls(), 0); |
| 302 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) { | 285 for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) { |
| 303 cursor.continueFunction(null_key_, new MockContinueCallbacks()); | 286 cursor_->continueFunction(null_key_, new MockContinueCallbacks()); |
| 304 EXPECT_EQ(++continue_calls, dispatcher_->continue_calls()); | 287 base::RunLoop().RunUntilIdle(); |
| 305 EXPECT_EQ(0, dispatcher_->prefetch_calls()); | 288 EXPECT_EQ(++continue_calls, mock_cursor_->continue_calls()); |
| 289 EXPECT_EQ(0, mock_cursor_->prefetch_calls()); |
| 306 } | 290 } |
| 307 | 291 |
| 308 // Initiate the prefetch | 292 // Initiate the prefetch |
| 309 cursor.continueFunction(null_key_, new MockContinueCallbacks()); | 293 cursor_->continueFunction(null_key_, new MockContinueCallbacks()); |
| 310 EXPECT_EQ(continue_calls, dispatcher_->continue_calls()); | 294 base::RunLoop().RunUntilIdle(); |
| 311 EXPECT_EQ(1, dispatcher_->prefetch_calls()); | 295 EXPECT_EQ(continue_calls, mock_cursor_->continue_calls()); |
| 312 EXPECT_EQ(0, dispatcher_->reset_calls()); | 296 EXPECT_EQ(1, mock_cursor_->prefetch_calls()); |
| 297 EXPECT_EQ(0, mock_cursor_->reset_calls()); |
| 313 | 298 |
| 314 // Now invalidate it | 299 // Now invalidate it |
| 315 cursor.ResetPrefetchCache(); | 300 cursor_->ResetPrefetchCache(); |
| 316 | 301 |
| 317 // No reset should have been sent since nothing has been received yet. | 302 // No reset should have been sent since nothing has been received yet. |
| 318 EXPECT_EQ(0, dispatcher_->reset_calls()); | 303 base::RunLoop().RunUntilIdle(); |
| 304 EXPECT_EQ(0, mock_cursor_->reset_calls()); |
| 319 | 305 |
| 320 // Fill the prefetch cache as requested. | 306 // Fill the prefetch cache as requested. |
| 321 int prefetch_count = dispatcher_->last_prefetch_count(); | 307 int prefetch_count = mock_cursor_->last_prefetch_count(); |
| 322 std::vector<IndexedDBKey> keys(prefetch_count); | 308 std::vector<IndexedDBKey> keys(prefetch_count); |
| 323 std::vector<IndexedDBKey> primary_keys(prefetch_count); | 309 std::vector<IndexedDBKey> primary_keys(prefetch_count); |
| 324 std::vector<WebIDBValue> values(prefetch_count); | 310 std::vector<WebIDBValue> values(prefetch_count); |
| 325 cursor.SetPrefetchData(keys, primary_keys, values); | 311 cursor_->SetPrefetchData(keys, primary_keys, values); |
| 326 | 312 |
| 327 // No reset should have been sent since prefetch data hasn't been used. | 313 // No reset should have been sent since prefetch data hasn't been used. |
| 328 EXPECT_EQ(0, dispatcher_->reset_calls()); | 314 base::RunLoop().RunUntilIdle(); |
| 315 EXPECT_EQ(0, mock_cursor_->reset_calls()); |
| 329 | 316 |
| 330 // The real dispatcher would call cursor->CachedContinue(), so do that: | 317 // The real dispatcher would call cursor->CachedContinue(), so do that: |
| 331 MockContinueCallbacks callbacks; | 318 MockContinueCallbacks callbacks; |
| 332 cursor.CachedContinue(&callbacks); | 319 cursor_->CachedContinue(&callbacks); |
| 333 | 320 |
| 334 // Now the cursor should have reset the rest of the cache. | 321 // Now the cursor should have reset the rest of the cache. |
| 335 EXPECT_EQ(1, dispatcher_->reset_calls()); | 322 base::RunLoop().RunUntilIdle(); |
| 336 EXPECT_EQ(1, dispatcher_->last_used_count()); | 323 EXPECT_EQ(1, mock_cursor_->reset_calls()); |
| 324 EXPECT_EQ(1, mock_cursor_->last_used_count()); |
| 325 |
| 326 cursor_.reset(); |
| 327 base::RunLoop().RunUntilIdle(); |
| 328 EXPECT_TRUE(mock_cursor_->destroyed()); |
| 337 } | 329 } |
| 338 | 330 |
| 339 } // namespace content | 331 } // namespace content |
| OLD | NEW |