blob: 73a7ec22e2b7b0f3db0d6d6e2f7144463e2a3d22 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/indexed_db/indexed_db_database.h"
#include "base/auto_reset.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/indexed_db/indexed_db.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_cursor.h"
#include "content/browser/indexed_db/indexed_db_database.h"
#include "content/browser/indexed_db/indexed_db_factory.h"
#include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
TEST(IndexedDBDatabaseTest, BackingStoreRetention) {
scoped_refptr<IndexedDBFakeBackingStore> backing_store =
new IndexedDBFakeBackingStore();
EXPECT_TRUE(backing_store->HasOneRef());
IndexedDBFactory* factory = 0;
scoped_refptr<IndexedDBDatabase> db = IndexedDBDatabase::Create(
ASCIIToUTF16("db"),
backing_store,
factory,
IndexedDBDatabase::Identifier());
EXPECT_FALSE(backing_store->HasOneRef()); // local and db
db = NULL;
EXPECT_TRUE(backing_store->HasOneRef()); // local
}
TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
scoped_refptr<IndexedDBFakeBackingStore> backing_store =
new IndexedDBFakeBackingStore();
EXPECT_TRUE(backing_store->HasOneRef()); // local
IndexedDBFactory* factory = 0;
scoped_refptr<IndexedDBDatabase> db =
IndexedDBDatabase::Create(ASCIIToUTF16("db"),
backing_store,
factory,
IndexedDBDatabase::Identifier());
EXPECT_FALSE(backing_store->HasOneRef()); // local and db
scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks());
scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
new MockIndexedDBDatabaseCallbacks());
const int64 transaction_id1 = 1;
db->OpenConnection(request1,
callbacks1,
transaction_id1,
IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
EXPECT_FALSE(backing_store->HasOneRef()); // db, connection count > 0
scoped_refptr<MockIndexedDBCallbacks> request2(new MockIndexedDBCallbacks());
scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks2(
new MockIndexedDBDatabaseCallbacks());
const int64 transaction_id2 = 2;
db->OpenConnection(request2,
callbacks2,
transaction_id2,
IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
EXPECT_FALSE(backing_store->HasOneRef()); // local and connection
request1->connection()->ForceClose();
EXPECT_FALSE(request1->connection()->IsConnected());
EXPECT_FALSE(backing_store->HasOneRef()); // local and connection
request2->connection()->ForceClose();
EXPECT_FALSE(request2->connection()->IsConnected());
EXPECT_TRUE(backing_store->HasOneRef());
EXPECT_FALSE(db->backing_store());
db = NULL;
}
TEST(IndexedDBDatabaseTest, ForcedClose) {
scoped_refptr<IndexedDBFakeBackingStore> backing_store =
new IndexedDBFakeBackingStore();
EXPECT_TRUE(backing_store->HasOneRef());
IndexedDBFactory* factory = 0;
scoped_refptr<IndexedDBDatabase> database =
IndexedDBDatabase::Create(ASCIIToUTF16("db"),
backing_store,
factory,
IndexedDBDatabase::Identifier());
EXPECT_FALSE(backing_store->HasOneRef()); // local and db
scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks(
new MockIndexedDBDatabaseCallbacks());
scoped_refptr<MockIndexedDBCallbacks> request(new MockIndexedDBCallbacks());
const int64 upgrade_transaction_id = 3;
database->OpenConnection(request,
callbacks,
upgrade_transaction_id,
IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
EXPECT_EQ(database, request->connection()->database());
const int64 transaction_id = 123;
const std::vector<int64> scope;
database->CreateTransaction(transaction_id,
request->connection(),
scope,
indexed_db::TRANSACTION_READ_ONLY);
request->connection()->ForceClose();
EXPECT_TRUE(backing_store->HasOneRef()); // local
EXPECT_TRUE(callbacks->abort_called());
}
class MockDeleteCallbacks : public IndexedDBCallbacks {
public:
MockDeleteCallbacks()
: IndexedDBCallbacks(NULL, 0, 0),
blocked_called_(false),
success_void_called_(false) {}
virtual void OnBlocked(int64 existing_version) OVERRIDE {
blocked_called_ = true;
}
virtual void OnSuccess() OVERRIDE { success_void_called_ = true; }
bool blocked_called() const { return blocked_called_; }
private:
virtual ~MockDeleteCallbacks() { EXPECT_TRUE(success_void_called_); }
bool blocked_called_;
bool success_void_called_;
};
TEST(IndexedDBDatabaseTest, PendingDelete) {
scoped_refptr<IndexedDBFakeBackingStore> backing_store =
new IndexedDBFakeBackingStore();
EXPECT_TRUE(backing_store->HasOneRef()); // local
IndexedDBFactory* factory = 0;
scoped_refptr<IndexedDBDatabase> db =
IndexedDBDatabase::Create(ASCIIToUTF16("db"),
backing_store,
factory,
IndexedDBDatabase::Identifier());
EXPECT_FALSE(backing_store->HasOneRef()); // local and db
scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks());
scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
new MockIndexedDBDatabaseCallbacks());
const int64 transaction_id1 = 1;
db->OpenConnection(request1,
callbacks1,
transaction_id1,
IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
EXPECT_FALSE(backing_store->HasOneRef()); // local and db
scoped_refptr<MockDeleteCallbacks> request2(new MockDeleteCallbacks());
db->DeleteDatabase(request2);
EXPECT_TRUE(request2->blocked_called());
EXPECT_FALSE(backing_store->HasOneRef()); // local and db
db->Close(request1->connection(), true /* forced */);
EXPECT_FALSE(db->backing_store());
EXPECT_TRUE(backing_store->HasOneRef()); // local
}
} // namespace content