This source file includes following definitions.
- destroyed_cursor_id_
 
- RequestIDBCursorPrefetch
 
- RequestIDBCursorPrefetchReset
 
- RequestIDBCursorAdvance
 
- RequestIDBCursorContinue
 
- CursorDestroyed
 
- prefetch_calls
 
- last_prefetch_count
 
- reset_calls
 
- last_used_count
 
- advance_calls
 
- continue_calls
 
- destroyed_cursor_id
 
- onSuccess
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
#include "base/memory/scoped_ptr.h"
#include "base/values.h"
#include "content/child/indexed_db/indexed_db_dispatcher.h"
#include "content/child/indexed_db/indexed_db_key_builders.h"
#include "content/child/indexed_db/webidbcursor_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/indexed_db/indexed_db_key.h"
#include "ipc/ipc_sync_message_filter.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebData.h"
#include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
using blink::WebData;
using blink::WebIDBCallbacks;
using blink::WebIDBDatabase;
using blink::WebIDBKey;
using blink::WebIDBKeyTypeNumber;
namespace content {
namespace {
class MockDispatcher : public IndexedDBDispatcher {
 public:
  MockDispatcher(ThreadSafeSender* thread_safe_sender)
      : IndexedDBDispatcher(thread_safe_sender),
        prefetch_calls_(0),
        last_prefetch_count_(0),
        reset_calls_(0),
        last_used_count_(0),
        advance_calls_(0),
        continue_calls_(0),
        destroyed_cursor_id_(0) {}
  virtual void RequestIDBCursorPrefetch(int n,
                                        WebIDBCallbacks* callbacks,
                                        int32 ipc_cursor_id) OVERRIDE {
    ++prefetch_calls_;
    last_prefetch_count_ = n;
    callbacks_.reset(callbacks);
  }
  virtual void RequestIDBCursorPrefetchReset(int used_prefetches,
                                             int unused_prefetches,
                                             int32 ipc_cursor_id) OVERRIDE {
    ++reset_calls_;
    last_used_count_ = used_prefetches;
  }
  virtual void RequestIDBCursorAdvance(unsigned long count,
                                       WebIDBCallbacks* callbacks,
                                       int32 ipc_cursor_id,
                                       int64 transaction_id) OVERRIDE {
    ++advance_calls_;
    callbacks_.reset(callbacks);
  }
  virtual void RequestIDBCursorContinue(const IndexedDBKey& key,
                                        const IndexedDBKey& primary_key,
                                        WebIDBCallbacks* callbacks,
                                        int32 ipc_cursor_id,
                                        int64 transaction_id) OVERRIDE {
    ++continue_calls_;
    callbacks_.reset(callbacks);
  }
  virtual void CursorDestroyed(int32 ipc_cursor_id) OVERRIDE {
    destroyed_cursor_id_ = ipc_cursor_id;
  }
  int prefetch_calls() { return prefetch_calls_; }
  int last_prefetch_count() { return last_prefetch_count_; }
  int reset_calls() { return reset_calls_; }
  int last_used_count() { return last_used_count_; }
  int advance_calls() { return advance_calls_; }
  int continue_calls() { return continue_calls_; }
  int32 destroyed_cursor_id() { return destroyed_cursor_id_; }
 private:
  int prefetch_calls_;
  int last_prefetch_count_;
  int reset_calls_;
  int last_used_count_;
  int advance_calls_;
  int continue_calls_;
  int32 destroyed_cursor_id_;
  scoped_ptr<WebIDBCallbacks> callbacks_;
};
class MockContinueCallbacks : public WebIDBCallbacks {
 public:
  MockContinueCallbacks(IndexedDBKey* key = 0) : key_(key) {}
  virtual void onSuccess(const WebIDBKey& key,
                         const WebIDBKey& primaryKey,
                         const WebData& value) {
    if (key_)
      *key_ = IndexedDBKeyBuilder::Build(key);
  }
 private:
  IndexedDBKey* key_;
};
}  
class WebIDBCursorImplTest : public testing::Test {
 public:
  WebIDBCursorImplTest() {
    null_key_.assignNull();
    sync_message_filter_ = new IPC::SyncMessageFilter(NULL);
    thread_safe_sender_ = new ThreadSafeSender(
        base::MessageLoopProxy::current(), sync_message_filter_.get());
    dispatcher_ =
        make_scoped_ptr(new MockDispatcher(thread_safe_sender_.get()));
  }
 protected:
  WebIDBKey null_key_;
  scoped_refptr<ThreadSafeSender> thread_safe_sender_;
  scoped_ptr<MockDispatcher> dispatcher_;
 private:
  scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
  DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImplTest);
};
TEST_F(WebIDBCursorImplTest, PrefetchTest) {
  const int64 transaction_id = 1;
  {
    WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
                            transaction_id,
                            thread_safe_sender_.get());
    
    int continue_calls = 0;
    EXPECT_EQ(dispatcher_->continue_calls(), 0);
    for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
      cursor.continueFunction(null_key_, new MockContinueCallbacks());
      EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
      EXPECT_EQ(0, dispatcher_->prefetch_calls());
    }
    
    
    const int kPrefetchRepetitions = 5;
    int expected_key = 0;
    int last_prefetch_count = 0;
    for (int repetitions = 0; repetitions < kPrefetchRepetitions;
         ++repetitions) {
      
      cursor.continueFunction(null_key_, new MockContinueCallbacks());
      EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
      EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
      
      int prefetch_count = dispatcher_->last_prefetch_count();
      EXPECT_GT(prefetch_count, last_prefetch_count);
      last_prefetch_count = prefetch_count;
      
      std::vector<IndexedDBKey> keys;
      std::vector<IndexedDBKey> primary_keys(prefetch_count);
      std::vector<WebData> values(prefetch_count);
      for (int i = 0; i < prefetch_count; ++i) {
        keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
      }
      cursor.SetPrefetchData(keys, primary_keys, values);
      
      
      
      
      for (int i = 0; i < prefetch_count; ++i) {
        IndexedDBKey key;
        cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
        EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
        EXPECT_EQ(repetitions + 1, dispatcher_->prefetch_calls());
        EXPECT_EQ(WebIDBKeyTypeNumber, key.type());
        EXPECT_EQ(expected_key++, key.number());
      }
    }
  }
  EXPECT_EQ(dispatcher_->destroyed_cursor_id(),
            WebIDBCursorImpl::kInvalidCursorId);
}
TEST_F(WebIDBCursorImplTest, AdvancePrefetchTest) {
  const int64 transaction_id = 1;
  WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
                          transaction_id,
                          thread_safe_sender_.get());
  
  EXPECT_EQ(0, dispatcher_->continue_calls());
  for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
    cursor.continueFunction(null_key_, new MockContinueCallbacks());
  }
  EXPECT_EQ(0, dispatcher_->prefetch_calls());
  
  cursor.continueFunction(null_key_, new MockContinueCallbacks());
  EXPECT_EQ(1, dispatcher_->prefetch_calls());
  EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
            dispatcher_->continue_calls());
  EXPECT_EQ(0, dispatcher_->advance_calls());
  const int prefetch_count = dispatcher_->last_prefetch_count();
  
  int expected_key = 0;
  std::vector<IndexedDBKey> keys;
  std::vector<IndexedDBKey> primary_keys(prefetch_count);
  std::vector<WebData> values(prefetch_count);
  for (int i = 0; i < prefetch_count; ++i) {
    keys.push_back(IndexedDBKey(expected_key + i, WebIDBKeyTypeNumber));
  }
  cursor.SetPrefetchData(keys, primary_keys, values);
  
  
  
  
  ASSERT_GE(prefetch_count, 5);
  
  IndexedDBKey key;
  cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
  EXPECT_EQ(0, key.number());
  
  cursor.advance(1, new MockContinueCallbacks(&key));
  EXPECT_EQ(1, key.number());
  
  cursor.continueFunction(null_key_, new MockContinueCallbacks(&key));
  EXPECT_EQ(2, key.number());
  
  cursor.advance(2, new MockContinueCallbacks(&key));
  EXPECT_EQ(4, key.number());
  EXPECT_EQ(0, dispatcher_->advance_calls());
  
  cursor.advance(WebIDBCursorImpl::kMaxPrefetchAmount,
                 new MockContinueCallbacks(&key));
  EXPECT_EQ(1, dispatcher_->advance_calls());
  EXPECT_EQ(1, dispatcher_->prefetch_calls());
  EXPECT_EQ(static_cast<int>(WebIDBCursorImpl::kPrefetchContinueThreshold),
            dispatcher_->continue_calls());
}
TEST_F(WebIDBCursorImplTest, PrefetchReset) {
  const int64 transaction_id = 1;
  WebIDBCursorImpl cursor(WebIDBCursorImpl::kInvalidCursorId,
                          transaction_id,
                          thread_safe_sender_.get());
  
  int continue_calls = 0;
  EXPECT_EQ(dispatcher_->continue_calls(), 0);
  for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) {
    cursor.continueFunction(null_key_, new MockContinueCallbacks());
    EXPECT_EQ(++continue_calls, dispatcher_->continue_calls());
    EXPECT_EQ(0, dispatcher_->prefetch_calls());
  }
  
  cursor.continueFunction(null_key_, new MockContinueCallbacks());
  EXPECT_EQ(continue_calls, dispatcher_->continue_calls());
  EXPECT_EQ(1, dispatcher_->prefetch_calls());
  EXPECT_EQ(0, dispatcher_->reset_calls());
  
  cursor.ResetPrefetchCache();
  
  EXPECT_EQ(0, dispatcher_->reset_calls());
  
  int prefetch_count = dispatcher_->last_prefetch_count();
  std::vector<IndexedDBKey> keys(prefetch_count);
  std::vector<IndexedDBKey> primary_keys(prefetch_count);
  std::vector<WebData> values(prefetch_count);
  cursor.SetPrefetchData(keys, primary_keys, values);
  
  EXPECT_EQ(0, dispatcher_->reset_calls());
  
  scoped_ptr<WebIDBCallbacks> callbacks(new MockContinueCallbacks());
  cursor.CachedContinue(callbacks.get());
  
  EXPECT_EQ(1, dispatcher_->reset_calls());
  EXPECT_EQ(1, dispatcher_->last_used_count());
}
}