15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/values.h"
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/child/indexed_db/indexed_db_dispatcher.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/child/indexed_db/indexed_db_key_builders.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/child/indexed_db/webidbcursor_impl.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/child/thread_safe_sender.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/common/indexed_db/indexed_db_key.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ipc/ipc_sync_message_filter.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebData.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing blink::WebBlobInfo;
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using blink::WebData;
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using blink::WebIDBCallbacks;
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using blink::WebIDBDatabase;
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using blink::WebIDBKey;
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using blink::WebIDBKeyTypeNumber;
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing blink::WebVector;
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace content {
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MockDispatcher : public IndexedDBDispatcher {
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  explicit MockDispatcher(ThreadSafeSender* thread_safe_sender)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : IndexedDBDispatcher(thread_safe_sender),
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        prefetch_calls_(0),
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        last_prefetch_count_(0),
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        reset_calls_(0),
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        last_used_count_(0),
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        advance_calls_(0),
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        continue_calls_(0),
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        destroyed_cursor_id_(0) {}
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void RequestIDBCursorPrefetch(int n,
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        WebIDBCallbacks* callbacks,
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        int32 ipc_cursor_id) OVERRIDE {
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ++prefetch_calls_;
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    last_prefetch_count_ = n;
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callbacks_.reset(callbacks);
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void RequestIDBCursorPrefetchReset(int used_prefetches,
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             int unused_prefetches,
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             int32 ipc_cursor_id) OVERRIDE {
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ++reset_calls_;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    last_used_count_ = used_prefetches;
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void RequestIDBCursorAdvance(unsigned long count,
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       WebIDBCallbacks* callbacks,
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       int32 ipc_cursor_id,
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       int64 transaction_id) OVERRIDE {
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ++advance_calls_;
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callbacks_.reset(callbacks);
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void RequestIDBCursorContinue(const IndexedDBKey& key,
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const IndexedDBKey& primary_key,
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        WebIDBCallbacks* callbacks,
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        int32 ipc_cursor_id,
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        int64 transaction_id) OVERRIDE {
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ++continue_calls_;
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    callbacks_.reset(callbacks);
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void CursorDestroyed(int32 ipc_cursor_id) OVERRIDE {
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    destroyed_cursor_id_ = ipc_cursor_id;
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int prefetch_calls() { return prefetch_calls_; }
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int last_prefetch_count() { return last_prefetch_count_; }
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int reset_calls() { return reset_calls_; }
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int last_used_count() { return last_used_count_; }
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int advance_calls() { return advance_calls_; }
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int continue_calls() { return continue_calls_; }
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int32 destroyed_cursor_id() { return destroyed_cursor_id_; }
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int prefetch_calls_;
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int last_prefetch_count_;
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int reset_calls_;
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int last_used_count_;
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int advance_calls_;
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int continue_calls_;
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int32 destroyed_cursor_id_;
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<WebIDBCallbacks> callbacks_;
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MockContinueCallbacks : public WebIDBCallbacks {
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MockContinueCallbacks(IndexedDBKey* key = 0,
995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        WebVector<WebBlobInfo>* webBlobInfo = 0)
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : key_(key), webBlobInfo_(webBlobInfo) {}
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void onSuccess(const WebIDBKey& key,
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         const WebIDBKey& primaryKey,
1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         const WebData& value,
1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         const WebVector<WebBlobInfo>& webBlobInfo) OVERRIDE {
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (key_)
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *key_ = IndexedDBKeyBuilder::Build(key);
1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (webBlobInfo_)
1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      *webBlobInfo_ = webBlobInfo;
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IndexedDBKey* key_;
1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  WebVector<WebBlobInfo>* webBlobInfo_;
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class WebIDBCursorImplTest : public testing::Test {
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebIDBCursorImplTest() {
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    null_key_.assignNull();
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    sync_message_filter_ = new IPC::SyncMessageFilter(NULL);
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    thread_safe_sender_ = new ThreadSafeSender(
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::MessageLoopProxy::current(), sync_message_filter_.get());
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dispatcher_ =
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        make_scoped_ptr(new MockDispatcher(thread_safe_sender_.get()));
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected:
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebIDBKey null_key_;
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<ThreadSafeSender> thread_safe_sender_;
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<MockDispatcher> dispatcher_;
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImplTest);
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebIDBCursorImplTest, PrefetchTest) {
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int64 transaction_id = 1;
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  {
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            transaction_id,
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            thread_safe_sender_.get());
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Call continue() until prefetching should kick in.
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int continue_calls = 0;
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(dispatcher_->continue_calls(), 0);
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      cursor.continueFunction(null_key_, new MockContinueCallbacks());
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(0, dispatcher_->prefetch_calls());
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Do enough repetitions to verify that the count grows each time,
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // but not so many that the maximum limit is hit.
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const int kPrefetchRepetitions = 5;
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int expected_key = 0;
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int last_prefetch_count = 0;
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (int repetitions = 0; repetitions < kPrefetchRepetitions;
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         ++repetitions) {
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Initiate the prefetch
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      cursor.continueFunction(null_key_, new MockContinueCallbacks());
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Verify that the requested count has increased since last time.
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      int prefetch_count = dispatcher_->last_prefetch_count();
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EXPECT_GT(prefetch_count, last_prefetch_count);
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      last_prefetch_count = prefetch_count;
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Fill the prefetch cache as requested.
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::vector<IndexedDBKey> keys;
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::vector<IndexedDBKey> primary_keys(prefetch_count);
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::vector<WebData> values(prefetch_count);
1795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      std::vector<WebVector<WebBlobInfo> > blob_info;
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (int i = 0; i < prefetch_count; ++i) {
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        blob_info.push_back(
1835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            WebVector<WebBlobInfo>(static_cast<size_t>(expected_key + i)));
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Note that the real dispatcher would call cursor->CachedContinue()
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // immediately after cursor->SetPrefetchData() to service the request
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // that initiated the prefetch.
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Verify that the cache is used for subsequent continue() calls.
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      for (int i = 0; i < prefetch_count; ++i) {
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        IndexedDBKey key;
1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        WebVector<WebBlobInfo> web_blob_info;
1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        cursor.continueFunction(
1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            null_key_, new MockContinueCallbacks(&key, &web_blob_info));
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        EXPECT_EQ(WebIDBKeyTypeNumber, key.type());
2015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        EXPECT_EQ(expected_key, static_cast<int>(web_blob_info.size()));
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        EXPECT_EQ(expected_key++, key.number());
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(dispatcher_->destroyed_cursor_id(),
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            WebIDBCursorImpl::kInvalidCursorId);
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int64 transaction_id = 1;
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          transaction_id,
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          thread_safe_sender_.get());
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Call continue() until prefetching should kick in.
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, dispatcher_->continue_calls());
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cursor.continueFunction(null_key_, new MockContinueCallbacks());
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, dispatcher_->prefetch_calls());
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Initiate the prefetch
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor.continueFunction(null_key_, new MockContinueCallbacks());
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1, dispatcher_->prefetch_calls());
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            dispatcher_->continue_calls());
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, dispatcher_->advance_calls());
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int prefetch_count = dispatcher_->last_prefetch_count();
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Fill the prefetch cache as requested.
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int expected_key = 0;
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<IndexedDBKey> keys;
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<IndexedDBKey> primary_keys(prefetch_count);
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<WebData> values(prefetch_count);
2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::vector<WebVector<WebBlobInfo> > blob_info;
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < prefetch_count; ++i) {
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    blob_info.push_back(
2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        WebVector<WebBlobInfo>(static_cast<size_t>(expected_key + i)));
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Note that the real dispatcher would call cursor->CachedContinue()
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // immediately after cursor->SetPrefetchData() to service the request
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // that initiated the prefetch.
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Need at least this many in the cache for the test steps.
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_GE(prefetch_count, 5);
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // IDBCursor.continue()
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IndexedDBKey key;
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, key.number());
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // IDBCursor.advance(1)
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor.advance(1, new MockContinueCallbacks(&key));
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1, key.number());
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // IDBCursor.continue()
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2, key.number());
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // IDBCursor.advance(2)
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor.advance(2, new MockContinueCallbacks(&key));
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(4, key.number());
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, dispatcher_->advance_calls());
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // IDBCursor.advance(lots) - beyond the fetched amount
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor.advance(WebIDBCursorImpl::kMaxPrefetchAmount,
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 new MockContinueCallbacks(&key));
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1, dispatcher_->advance_calls());
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1, dispatcher_->prefetch_calls());
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            dispatcher_->continue_calls());
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebIDBCursorImplTest, PrefetchReset) {
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int64 transaction_id = 1;
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          transaction_id,
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          thread_safe_sender_.get());
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Call continue() until prefetching should kick in.
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int continue_calls = 0;
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(dispatcher_->continue_calls(), 0);
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cursor.continueFunction(null_key_, new MockContinueCallbacks());
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(0, dispatcher_->prefetch_calls());
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Initiate the prefetch
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor.continueFunction(null_key_, new MockContinueCallbacks());
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1, dispatcher_->prefetch_calls());
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, dispatcher_->reset_calls());
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Now invalidate it
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor.ResetPrefetchCache();
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // No reset should have been sent since nothing has been received yet.
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, dispatcher_->reset_calls());
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Fill the prefetch cache as requested.
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int prefetch_count = dispatcher_->last_prefetch_count();
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<IndexedDBKey> keys(prefetch_count);
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<IndexedDBKey> primary_keys(prefetch_count);
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<WebData> values(prefetch_count);
3145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::vector<WebVector<WebBlobInfo> > blob_info(prefetch_count);
3155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  cursor.SetPrefetchData(keys, primary_keys, values, blob_info);
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // No reset should have been sent since prefetch data hasn't been used.
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, dispatcher_->reset_calls());
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The real dispatcher would call cursor->CachedContinue(), so do that:
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<WebIDBCallbacks> callbacks(new MockContinueCallbacks());
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor.CachedContinue(callbacks.get());
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Now the cursor should have reset the rest of the cache.
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1, dispatcher_->reset_calls());
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1, dispatcher_->last_used_count());
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace content
330