// Copyright 2013 The Chromium Authors
// 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/instance/database.h"

#include <stdint.h>

#include <set>
#include <string>
#include <utility>

#include "base/auto_reset.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "components/services/storage/indexed_db/locks/partitioned_lock_manager.h"
#include "components/services/storage/privileged/mojom/indexed_db_client_state_checker.mojom.h"
#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/browser/indexed_db/instance/backing_store.h"
#include "content/browser/indexed_db/instance/bucket_context.h"
#include "content/browser/indexed_db/instance/connection.h"
#include "content/browser/indexed_db/instance/cursor.h"
#include "content/browser/indexed_db/instance/database_callbacks.h"
#include "content/browser/indexed_db/instance/factory_client.h"
#include "content/browser/indexed_db/instance/fake_transaction.h"
#include "content/browser/indexed_db/instance/mock_factory_client.h"
#include "content/browser/indexed_db/instance/transaction.h"
#include "content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "storage/browser/test/mock_quota_manager.h"
#include "storage/browser/test/mock_quota_manager_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"

using blink::IndexedDBDatabaseMetadata;
using blink::IndexedDBIndexKeys;
using blink::IndexedDBKey;
using blink::IndexedDBKeyPath;

namespace content::indexed_db {

class DatabaseTest : public ::testing::Test {
 public:
  DatabaseTest() = default;

  void SetUp() override {
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
    quota_manager_ = base::MakeRefCounted<storage::MockQuotaManager>(
        /*is_incognito=*/false, temp_dir_.GetPath(),
        base::SingleThreadTaskRunner::GetCurrentDefault(),
        /*special_storage_policy=*/nullptr);

    quota_manager_proxy_ = base::MakeRefCounted<storage::MockQuotaManagerProxy>(
        quota_manager_.get(),
        base::SingleThreadTaskRunner::GetCurrentDefault().get());

    BucketContext::Delegate delegate;
    delegate.on_ready_for_destruction =
        base::BindOnce(&DatabaseTest::OnBucketContextReadyForDestruction,
                       weak_factory_.GetWeakPtr());

    bucket_context_ = std::make_unique<BucketContext>(
        storage::BucketInfo(), temp_dir_.GetPath(), std::move(delegate),
        quota_manager_proxy_,
        /*io_task_runner=*/base::SequencedTaskRunner::GetCurrentDefault(),
        /*blob_storage_context=*/mojo::NullRemote(),
        /*file_system_access_context=*/mojo::NullRemote(), base::DoNothing());

    bucket_context_->InitBackingStoreIfNeeded(true);
    db_ = bucket_context_->AddDatabase(
        u"db", std::make_unique<Database>(u"db", *bucket_context_,
                                          Database::Identifier()));
  }

  void TearDown() override { db_ = nullptr; }

  void OnBucketContextReadyForDestruction() { bucket_context_.reset(); }

  void RunPostedTasks() {
    base::RunLoop run_loop;
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, run_loop.QuitClosure());
    run_loop.Run();
  }

 protected:
  base::test::TaskEnvironment task_environment_;

  base::ScopedTempDir temp_dir_;
  std::unique_ptr<BucketContext> bucket_context_;
  scoped_refptr<storage::MockQuotaManager> quota_manager_;
  scoped_refptr<storage::MockQuotaManagerProxy> quota_manager_proxy_;

  // As this is owned by `bucket_context_`, tests that cause the database to
  // be destroyed must manually reset this to null to avoid triggering dangling
  // pointer warnings.
  raw_ptr<Database> db_ = nullptr;

  base::WeakPtrFactory<DatabaseTest> weak_factory_{this};
};

TEST_F(DatabaseTest, ConnectionLifecycle) {
  MockMojoDatabaseCallbacks database_callbacks;
  MockFactoryClient request1;
  const int64_t transaction_id1 = 1;
  auto connection1 = std::make_unique<PendingConnection>(
      std::make_unique<ThunkFactoryClient>(request1),
      std::make_unique<DatabaseCallbacks>(
          database_callbacks.BindNewEndpointAndPassDedicatedRemote()),
      transaction_id1, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
      mojo::NullAssociatedReceiver());
  db_->ScheduleOpenConnection(std::move(connection1));
  RunPostedTasks();

  MockMojoDatabaseCallbacks database_callbacks2;
  MockFactoryClient request2;
  const int64_t transaction_id2 = 2;
  auto connection2 = std::make_unique<PendingConnection>(
      std::make_unique<ThunkFactoryClient>(request2),
      std::make_unique<DatabaseCallbacks>(
          database_callbacks2.BindNewEndpointAndPassDedicatedRemote()),
      transaction_id2, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
      mojo::NullAssociatedReceiver());
  db_->ScheduleOpenConnection(std::move(connection2));
  RunPostedTasks();
  db_ = nullptr;

  EXPECT_TRUE(request1.connection());
  request1.connection()->CloseAndReportForceClose();
  EXPECT_FALSE(request1.connection()->IsConnected());

  EXPECT_TRUE(request2.connection());
  request2.connection()->CloseAndReportForceClose();
  EXPECT_FALSE(request2.connection()->IsConnected());

  RunPostedTasks();

  EXPECT_TRUE(bucket_context_->GetDatabasesForTesting().empty());
}

TEST_F(DatabaseTest, ForcedClose) {
  MockMojoDatabaseCallbacks database_callbacks;
  MockFactoryClient request;
  const int64_t upgrade_transaction_id = 3;
  auto connection = std::make_unique<PendingConnection>(
      std::make_unique<ThunkFactoryClient>(request),
      std::make_unique<DatabaseCallbacks>(
          database_callbacks.BindNewEndpointAndPassDedicatedRemote()),
      upgrade_transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
      mojo::NullAssociatedReceiver());
  db_->ScheduleOpenConnection(std::move(connection));
  RunPostedTasks();

  EXPECT_EQ(db_, request.connection()->database().get());

  request.connection()->CreateTransaction(
      mojo::NullAssociatedReceiver(), /*transaction_id=*/123,
      /*object_store_ids=*/{}, blink::mojom::IDBTransactionMode::ReadOnly,
      blink::mojom::IDBTransactionDurability::Relaxed);
  db_ = nullptr;

  base::RunLoop run_loop;
  EXPECT_CALL(database_callbacks, ForcedClose)
      .WillOnce(base::test::RunClosure(run_loop.QuitClosure()));
  request.connection()->CloseAndReportForceClose();
  run_loop.Run();
}

namespace {

class FakeFactoryClient : public FactoryClient {
 public:
  FakeFactoryClient() : FactoryClient(mojo::NullAssociatedRemote()) {}
  ~FakeFactoryClient() override = default;

  FakeFactoryClient(const FakeFactoryClient&) = delete;
  FakeFactoryClient& operator=(const FakeFactoryClient&) = delete;

  void OnBlocked(int64_t existing_version) override { blocked_called_ = true; }
  void OnDeleteSuccess(int64_t old_version) override { success_called_ = true; }
  void OnError(const DatabaseError& error) override { error_called_ = true; }

  bool blocked_called() const { return blocked_called_; }
  bool success_called() const { return success_called_; }
  bool error_called() const { return error_called_; }

 private:
  bool blocked_called_ = false;
  bool success_called_ = false;
  bool error_called_ = false;
};

}  // namespace

TEST_F(DatabaseTest, PendingDelete) {
  MockFactoryClient request1;
  const int64_t transaction_id1 = 1;
  MockMojoDatabaseCallbacks database_callbacks1;
  auto connection = std::make_unique<PendingConnection>(
      std::make_unique<ThunkFactoryClient>(request1),
      std::make_unique<DatabaseCallbacks>(
          database_callbacks1.BindNewEndpointAndPassDedicatedRemote()),
      transaction_id1, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
      mojo::NullAssociatedReceiver());
  db_->ScheduleOpenConnection(std::move(connection));
  RunPostedTasks();

  EXPECT_EQ(db_->ConnectionCount(), 1UL);
  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL);
  EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);

  base::RunLoop run_loop;
  FakeFactoryClient request2;
  db_->ScheduleDeleteDatabase(std::make_unique<ThunkFactoryClient>(request2),
                              run_loop.QuitClosure());
  RunPostedTasks();
  EXPECT_EQ(db_->ConnectionCount(), 1UL);
  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
  EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);

  EXPECT_FALSE(request2.blocked_called());
  request1.connection()->VersionChangeIgnored();
  EXPECT_TRUE(request2.blocked_called());
  EXPECT_EQ(db_->ConnectionCount(), 1UL);
  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
  EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);

  db_->ForceCloseAndRunTasks();
  db_ = nullptr;

  run_loop.Run();
  EXPECT_FALSE(db_);

  EXPECT_TRUE(request2.success_called());
}

TEST_F(DatabaseTest, OpenDeleteClear) {
  const int64_t kDatabaseVersion = 1;

  MockFactoryClient request1(
      /*expect_connection=*/true);
  MockMojoDatabaseCallbacks database_callbacks1;
  const int64_t transaction_id1 = 1;
  auto connection1 = std::make_unique<PendingConnection>(
      std::make_unique<ThunkFactoryClient>(request1),
      std::make_unique<DatabaseCallbacks>(
          database_callbacks1.BindNewEndpointAndPassDedicatedRemote()),
      transaction_id1, kDatabaseVersion, mojo::NullAssociatedReceiver());
  db_->ScheduleOpenConnection(std::move(connection1));
  RunPostedTasks();

  EXPECT_EQ(db_->ConnectionCount(), 1UL);
  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
  EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);

  MockFactoryClient request2(
      /*expect_connection=*/false);
  MockMojoDatabaseCallbacks database_callbacks2;
  const int64_t transaction_id2 = 2;
  auto connection2 = std::make_unique<PendingConnection>(
      std::make_unique<ThunkFactoryClient>(request2),
      std::make_unique<DatabaseCallbacks>(
          database_callbacks2.BindNewEndpointAndPassDedicatedRemote()),
      transaction_id2, kDatabaseVersion, mojo::NullAssociatedReceiver());
  db_->ScheduleOpenConnection(std::move(connection2));
  RunPostedTasks();

  EXPECT_EQ(db_->ConnectionCount(), 1UL);
  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
  EXPECT_EQ(db_->PendingOpenDeleteCount(), 1UL);

  MockFactoryClient request3(
      /*expect_connection=*/false);
  MockMojoDatabaseCallbacks database_callbacks3;
  const int64_t transaction_id3 = 3;
  auto connection3 = std::make_unique<PendingConnection>(
      std::make_unique<ThunkFactoryClient>(request3),
      std::make_unique<DatabaseCallbacks>(
          database_callbacks3.BindNewEndpointAndPassDedicatedRemote()),
      transaction_id3, kDatabaseVersion, mojo::NullAssociatedReceiver());
  db_->ScheduleOpenConnection(std::move(connection3));
  RunPostedTasks();

  EXPECT_TRUE(request1.upgrade_called());

  EXPECT_EQ(db_->ConnectionCount(), 1UL);
  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
  EXPECT_EQ(db_->PendingOpenDeleteCount(), 2UL);

  EXPECT_CALL(database_callbacks1, ForcedClose);
  EXPECT_CALL(database_callbacks2, ForcedClose);
  EXPECT_CALL(database_callbacks3, ForcedClose);

  db_->ForceCloseAndRunTasks();
  db_ = nullptr;
  database_callbacks1.FlushForTesting();

  EXPECT_TRUE(request1.error_called());
  EXPECT_TRUE(request2.error_called());
  EXPECT_TRUE(request3.error_called());
}

TEST_F(DatabaseTest, ForceDelete) {
  MockFactoryClient request1;
  MockMojoDatabaseCallbacks database_callbacks;
  const int64_t transaction_id1 = 1;
  auto connection = std::make_unique<PendingConnection>(
      std::make_unique<ThunkFactoryClient>(request1),
      std::make_unique<DatabaseCallbacks>(
          database_callbacks.BindNewEndpointAndPassDedicatedRemote()),
      transaction_id1, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
      mojo::NullAssociatedReceiver());
  db_->ScheduleOpenConnection(std::move(connection));
  RunPostedTasks();

  EXPECT_EQ(db_->ConnectionCount(), 1UL);
  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL);
  EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);

  base::RunLoop run_loop;
  FakeFactoryClient request2;
  db_->ScheduleDeleteDatabase(std::make_unique<ThunkFactoryClient>(request2),
                              run_loop.QuitClosure());
  RunPostedTasks();
  EXPECT_FALSE(run_loop.AnyQuitCalled());
  db_->ForceCloseAndRunTasks();
  db_ = nullptr;
  run_loop.Run();
  EXPECT_FALSE(db_);
  EXPECT_FALSE(request2.blocked_called());
  EXPECT_TRUE(request2.success_called());
}

TEST_F(DatabaseTest, ForceCloseWhileOpenPending) {
  // Verify that pending connection requests are handled correctly during a
  // ForceClose.
  MockFactoryClient request1;
  MockMojoDatabaseCallbacks database_callbacks1;
  const int64_t transaction_id1 = 1;
  auto connection1 = std::make_unique<PendingConnection>(
      std::make_unique<ThunkFactoryClient>(request1),
      std::make_unique<DatabaseCallbacks>(
          database_callbacks1.BindNewEndpointAndPassDedicatedRemote()),
      transaction_id1, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
      mojo::NullAssociatedReceiver());
  db_->ScheduleOpenConnection(std::move(connection1));
  RunPostedTasks();

  EXPECT_EQ(db_->ConnectionCount(), 1UL);
  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL);
  EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);

  MockFactoryClient request2(/*expect_connection=*/false);
  MockMojoDatabaseCallbacks database_callbacks2;

  const int64_t transaction_id2 = 2;
  auto connection2 = std::make_unique<PendingConnection>(
      std::make_unique<ThunkFactoryClient>(request2),
      std::make_unique<DatabaseCallbacks>(
          database_callbacks2.BindNewEndpointAndPassDedicatedRemote()),
      transaction_id2, 3, mojo::NullAssociatedReceiver());
  db_->ScheduleOpenConnection(std::move(connection2));
  RunPostedTasks();

  EXPECT_EQ(db_->ConnectionCount(), 1UL);
  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
  EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);

  db_->ForceCloseAndRunTasks();
  db_ = nullptr;
  RunPostedTasks();
  EXPECT_FALSE(db_);
}

TEST_F(DatabaseTest, ForceCloseWhileOpenAndDeletePending) {
  // Verify that pending connection requests are handled correctly during a
  // ForceClose.
  MockFactoryClient request1;
  MockMojoDatabaseCallbacks database_callbacks1;
  const int64_t transaction_id1 = 1;
  auto connection1 = std::make_unique<PendingConnection>(
      std::make_unique<ThunkFactoryClient>(request1),
      std::make_unique<DatabaseCallbacks>(
          database_callbacks1.BindNewEndpointAndPassDedicatedRemote()),
      transaction_id1, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
      mojo::NullAssociatedReceiver());
  db_->ScheduleOpenConnection(std::move(connection1));
  RunPostedTasks();

  EXPECT_EQ(db_->ConnectionCount(), 1UL);
  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL);
  EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);

  MockFactoryClient request2(false);
  MockMojoDatabaseCallbacks database_callbacks2;
  const int64_t transaction_id2 = 2;
  auto connection2 = std::make_unique<PendingConnection>(
      std::make_unique<ThunkFactoryClient>(request2),
      std::make_unique<DatabaseCallbacks>(
          database_callbacks2.BindNewEndpointAndPassDedicatedRemote()),
      transaction_id2, 3, mojo::NullAssociatedReceiver());
  db_->ScheduleOpenConnection(std::move(connection2));
  RunPostedTasks();

  base::RunLoop run_loop;
  auto request3 = std::make_unique<FakeFactoryClient>();
  db_->ScheduleDeleteDatabase(std::move(request3), run_loop.QuitClosure());
  RunPostedTasks();
  EXPECT_FALSE(run_loop.AnyQuitCalled());

  EXPECT_EQ(db_->ConnectionCount(), 1UL);
  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
  EXPECT_EQ(db_->PendingOpenDeleteCount(), 1UL);

  db_->ForceCloseAndRunTasks();
  db_ = nullptr;
  run_loop.Run();
}

leveldb::Status DummyOperation(Transaction* transaction) {
  return leveldb::Status::OK();
}

class DatabaseOperationTest : public DatabaseTest {
 public:
  DatabaseOperationTest() : commit_success_(leveldb::Status::OK()) {}

  DatabaseOperationTest(const DatabaseOperationTest&) = delete;
  DatabaseOperationTest& operator=(const DatabaseOperationTest&) = delete;

  void SetUp() override {
    DatabaseTest::SetUp();

    const int64_t transaction_id = 1;
    auto connection = std::make_unique<PendingConnection>(
        std::make_unique<ThunkFactoryClient>(request_),
        std::make_unique<DatabaseCallbacks>(mojo::NullAssociatedRemote()),
        transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION,
        mojo::NullAssociatedReceiver());
    db_->ScheduleOpenConnection(std::move(connection));
    RunPostedTasks();
    EXPECT_EQ(IndexedDBDatabaseMetadata::NO_VERSION, db_->metadata().version);

    EXPECT_TRUE(request_.connection());
    transaction_ = request_.connection()->CreateVersionChangeTransaction(
        transaction_id, /*scope=*/std::set<int64_t>(),
        new FakeTransaction(commit_success_,
                            blink::mojom::IDBTransactionMode::VersionChange,
                            bucket_context_->backing_store()->AsWeakPtr()));

    std::vector<PartitionedLockManager::PartitionedLockRequest> lock_requests =
        {{GetDatabaseLockId(db_->metadata().name),
          PartitionedLockManager::LockType::kExclusive}};
    db_->lock_manager().AcquireLocks(
        std::move(lock_requests), *transaction_->mutable_locks_receiver(),
        base::BindOnce(&Transaction::Start, transaction_->AsWeakPtr()));

    // Add a dummy task which takes the place of the VersionChangeOperation
    // which kicks off the upgrade. This ensures that the transaction has
    // processed at least one task before the CreateObjectStore call.
    transaction_->ScheduleTask(base::BindOnce(&DummyOperation));
    // Run posted tasks to execute the dummy operation and ensure that it is
    // stored in the connection.
    RunPostedTasks();
  }

 protected:
  MockFactoryClient request_;

  // As this is owned by `Connection`, tests that cause the transaction
  // to be committed must manually reset this to null to avoid triggering
  // dangling pointer warnings.
  raw_ptr<Transaction> transaction_ = nullptr;
  leveldb::Status commit_success_;
};

TEST_F(DatabaseOperationTest, CreateObjectStore) {
  EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
  const int64_t store_id = 1001;
  leveldb::Status s =
      db_->CreateObjectStoreOperation(store_id, u"store", IndexedDBKeyPath(),
                                      /*auto_increment=*/false, transaction_);
  EXPECT_TRUE(s.ok());
  transaction_->SetCommitFlag();
  transaction_ = nullptr;
  RunPostedTasks();
  EXPECT_TRUE(bucket_context_);
  EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
}

TEST_F(DatabaseOperationTest, CreateIndex) {
  EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
  const int64_t store_id = 1001;
  leveldb::Status s =
      db_->CreateObjectStoreOperation(store_id, u"store", IndexedDBKeyPath(),
                                      /*auto_increment=*/false, transaction_);
  EXPECT_TRUE(s.ok());
  EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
  const int64_t index_id = 2002;
  s = db_->CreateIndexOperation(store_id, index_id, u"index",
                                IndexedDBKeyPath(), /*unique=*/false,
                                /*multi_entry=*/false, transaction_);
  EXPECT_TRUE(s.ok());
  EXPECT_EQ(
      1ULL,
      db_->metadata().object_stores.find(store_id)->second.indexes.size());
  transaction_->SetCommitFlag();
  transaction_ = nullptr;
  RunPostedTasks();
  EXPECT_TRUE(bucket_context_);
  EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
  EXPECT_EQ(
      1ULL,
      db_->metadata().object_stores.find(store_id)->second.indexes.size());
}

class DatabaseOperationAbortTest : public DatabaseOperationTest {
 public:
  DatabaseOperationAbortTest() {
    commit_success_ = leveldb::Status::NotFound("Bummer.");
  }

  DatabaseOperationAbortTest(const DatabaseOperationAbortTest&) = delete;
  DatabaseOperationAbortTest& operator=(const DatabaseOperationAbortTest&) =
      delete;
};

TEST_F(DatabaseOperationAbortTest, CreateObjectStore) {
  EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
  const int64_t store_id = 1001;
  leveldb::Status s =
      db_->CreateObjectStoreOperation(store_id, u"store", IndexedDBKeyPath(),
                                      /*auto_increment=*/false, transaction_);
  EXPECT_TRUE(s.ok());
  EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
  db_ = nullptr;
  transaction_->SetCommitFlag();
  RunPostedTasks();
  // A transaction error results in a deleted db.
  EXPECT_TRUE(bucket_context_->GetDatabasesForTesting().empty());
}

TEST_F(DatabaseOperationAbortTest, CreateIndex) {
  EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
  const int64_t store_id = 1001;
  leveldb::Status s =
      db_->CreateObjectStoreOperation(store_id, u"store", IndexedDBKeyPath(),
                                      /*auto_increment=*/false, transaction_);
  EXPECT_TRUE(s.ok());
  EXPECT_EQ(1ULL, db_->metadata().object_stores.size());
  const int64_t index_id = 2002;
  s = db_->CreateIndexOperation(store_id, index_id, u"index",
                                IndexedDBKeyPath(), /*unique=*/false,
                                /*multi_entry=*/false, transaction_);
  EXPECT_TRUE(s.ok());
  EXPECT_EQ(
      1ULL,
      db_->metadata().object_stores.find(store_id)->second.indexes.size());
  db_ = nullptr;
  transaction_->SetCommitFlag();
  RunPostedTasks();
  // A transaction error results in a deleted db.
  EXPECT_TRUE(bucket_context_->GetDatabasesForTesting().empty());
}

TEST_F(DatabaseOperationTest, CreatePutDelete) {
  EXPECT_EQ(0ULL, db_->metadata().object_stores.size());
  const int64_t store_id = 1001;

  leveldb::Status s =
      db_->CreateObjectStoreOperation(store_id, u"store", IndexedDBKeyPath(),
                                      /*auto_increment=*/false, transaction_);
  EXPECT_TRUE(s.ok());
  EXPECT_EQ(1ULL, db_->metadata().object_stores.size());

  IndexedDBValue value("value1", {});
  std::unique_ptr<IndexedDBKey> key(std::make_unique<IndexedDBKey>("key"));
  std::vector<IndexedDBIndexKeys> index_keys;
  base::MockCallback<blink::mojom::IDBTransaction::PutCallback> callback;

  // Set in-flight memory to a reasonably large number to prevent underflow in
  // `PutOperation`
  transaction_->in_flight_memory() += 1000;

  auto put_params = std::make_unique<Database::PutOperationParams>();
  put_params->object_store_id = store_id;
  put_params->value = value;
  put_params->key = std::move(key);
  put_params->put_mode = blink::mojom::IDBPutMode::AddOnly;
  put_params->callback = callback.Get();
  put_params->index_keys = index_keys;
  s = db_->PutOperation(std::move(put_params), transaction_);
  EXPECT_TRUE(s.ok());

  s = db_->DeleteObjectStoreOperation(store_id, transaction_);
  EXPECT_TRUE(s.ok());

  EXPECT_EQ(0ULL, db_->metadata().object_stores.size());

  transaction_->SetCommitFlag();
  transaction_ = nullptr;
  RunPostedTasks();
  // A transaction error would have resulted in a deleted db.
  EXPECT_FALSE(bucket_context_->GetDatabasesForTesting().empty());
  EXPECT_TRUE(s.ok());
}

}  // namespace content::indexed_db
