// 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 backing_store = new IndexedDBFakeBackingStore(); EXPECT_TRUE(backing_store->HasOneRef()); IndexedDBFactory* factory = 0; scoped_refptr 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 backing_store = new IndexedDBFakeBackingStore(); EXPECT_TRUE(backing_store->HasOneRef()); // local IndexedDBFactory* factory = 0; scoped_refptr db = IndexedDBDatabase::Create(ASCIIToUTF16("db"), backing_store, factory, IndexedDBDatabase::Identifier()); EXPECT_FALSE(backing_store->HasOneRef()); // local and db scoped_refptr request1(new MockIndexedDBCallbacks()); scoped_refptr 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 request2(new MockIndexedDBCallbacks()); scoped_refptr 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 backing_store = new IndexedDBFakeBackingStore(); EXPECT_TRUE(backing_store->HasOneRef()); IndexedDBFactory* factory = 0; scoped_refptr database = IndexedDBDatabase::Create(ASCIIToUTF16("db"), backing_store, factory, IndexedDBDatabase::Identifier()); EXPECT_FALSE(backing_store->HasOneRef()); // local and db scoped_refptr callbacks( new MockIndexedDBDatabaseCallbacks()); scoped_refptr 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 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 backing_store = new IndexedDBFakeBackingStore(); EXPECT_TRUE(backing_store->HasOneRef()); // local IndexedDBFactory* factory = 0; scoped_refptr db = IndexedDBDatabase::Create(ASCIIToUTF16("db"), backing_store, factory, IndexedDBDatabase::Identifier()); EXPECT_FALSE(backing_store->HasOneRef()); // local and db scoped_refptr request1(new MockIndexedDBCallbacks()); scoped_refptr 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 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