// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stddef.h>

#include <memory>

#include "base/json/json_writer.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/values.h"
#include "components/value_store/testing_value_store.h"
#include "extensions/browser/api/storage/settings_storage_quota_enforcer.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace extensions {

// To save typing value_store::ValueStore::DEFAULTS/IGNORE_QUOTA everywhere.
const value_store::ValueStore::WriteOptions DEFAULTS =
    value_store::ValueStore::DEFAULTS;
const value_store::ValueStore::WriteOptions IGNORE_QUOTA =
    value_store::ValueStore::IGNORE_QUOTA;

class ExtensionSettingsQuotaTest : public testing::Test {
 public:
  ExtensionSettingsQuotaTest()
      : byte_value_1_(1),
        byte_value_16_("sixteen bytes."),
        byte_value_256_(base::Value(base::Value::Type::LIST)),
        delegate_(new value_store::TestingValueStore()) {
    for (int i = 1; i < 89; ++i) {
      byte_value_256_.GetList().Append(i);
    }
    ValidateByteValues();
  }

  void ValidateByteValues() {
    std::string validate_sizes = base::WriteJson(byte_value_1_).value_or("");
    ASSERT_EQ(1u, validate_sizes.size());
    validate_sizes = base::WriteJson(byte_value_16_).value_or("");
    ASSERT_EQ(16u, validate_sizes.size());
    validate_sizes = base::WriteJson(byte_value_256_).value_or("");
    ASSERT_EQ(256u, validate_sizes.size());
  }

  void TearDown() override { ASSERT_TRUE(storage_.get() != nullptr); }

 protected:
  // Creates |storage_|.  Must only be called once.
  void CreateStorage(
      size_t quota_bytes, size_t quota_bytes_per_item, size_t max_items) {
    ASSERT_TRUE(storage_.get() == nullptr);
    SettingsStorageQuotaEnforcer::Limits limits =
        { quota_bytes, quota_bytes_per_item, max_items };
    storage_ = std::make_unique<SettingsStorageQuotaEnforcer>(
        limits, base::WrapUnique(delegate_.get()));
  }

  // Returns whether the settings in |storage_| and |delegate_| are the same as
  // |settings|.
  bool SettingsEqual(const base::DictValue& settings) {
    return settings == storage_->Get().settings() &&
           settings == delegate_->Get().settings();
  }

  // Values with different serialized sizes.
  base::Value byte_value_1_;
  base::Value byte_value_16_;
  base::Value byte_value_256_;

  // Quota enforcing storage area being tested.
  std::unique_ptr<SettingsStorageQuotaEnforcer> storage_;

  // In-memory storage area being delegated to.  Always owned by |storage_|.
  raw_ptr<value_store::TestingValueStore> delegate_;
};

TEST_F(ExtensionSettingsQuotaTest, ZeroQuotaBytes) {
  base::DictValue empty;
  CreateStorage(0, UINT_MAX, UINT_MAX);

  EXPECT_FALSE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  EXPECT_TRUE(storage_->Remove("a").status().ok());
  EXPECT_TRUE(storage_->Remove("b").status().ok());
  EXPECT_TRUE(SettingsEqual(empty));
}

TEST_F(ExtensionSettingsQuotaTest, KeySizeTakenIntoAccount) {
  base::DictValue empty;
  CreateStorage(8u, UINT_MAX, UINT_MAX);
  EXPECT_FALSE(
      storage_->Set(DEFAULTS, "Really long key", byte_value_1_).status().ok());
  EXPECT_TRUE(SettingsEqual(empty));
}

TEST_F(ExtensionSettingsQuotaTest, SmallByteQuota) {
  base::DictValue settings;
  CreateStorage(8u, UINT_MAX, UINT_MAX);

  EXPECT_TRUE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  settings.Set("a", byte_value_1_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  EXPECT_FALSE(storage_->Set(DEFAULTS, "b", byte_value_16_).status().ok());
  EXPECT_FALSE(storage_->Set(DEFAULTS, "c", byte_value_256_).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, MediumByteQuota) {
  base::DictValue settings;
  CreateStorage(40, UINT_MAX, UINT_MAX);

  base::DictValue to_set;
  to_set.Set("a", byte_value_1_.Clone());
  to_set.Set("b", byte_value_16_.Clone());
  EXPECT_TRUE(storage_->Set(DEFAULTS, to_set).status().ok());
  settings.Set("a", byte_value_1_.Clone());
  settings.Set("b", byte_value_16_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  // Should be able to set value to other under-quota value.
  to_set.Set("a", byte_value_16_.Clone());
  EXPECT_TRUE(storage_->Set(DEFAULTS, to_set).status().ok());
  settings.Set("a", byte_value_16_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  EXPECT_FALSE(storage_->Set(DEFAULTS, "c", byte_value_256_).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, ZeroMaxKeys) {
  base::DictValue empty;
  CreateStorage(UINT_MAX, UINT_MAX, 0);

  EXPECT_FALSE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  EXPECT_TRUE(storage_->Remove("a").status().ok());
  EXPECT_TRUE(storage_->Remove("b").status().ok());
  EXPECT_TRUE(SettingsEqual(empty));
}

TEST_F(ExtensionSettingsQuotaTest, SmallMaxKeys) {
  base::DictValue settings;
  CreateStorage(UINT_MAX, UINT_MAX, 1);

  EXPECT_TRUE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  settings.Set("a", byte_value_1_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  // Should be able to set existing key to other value without going over quota.
  EXPECT_TRUE(storage_->Set(DEFAULTS, "a", byte_value_16_).status().ok());
  settings.Set("a", byte_value_16_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  EXPECT_FALSE(storage_->Set(DEFAULTS, "b", byte_value_16_).status().ok());
  EXPECT_FALSE(storage_->Set(DEFAULTS, "c", byte_value_256_).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, MediumMaxKeys) {
  base::DictValue settings;
  CreateStorage(UINT_MAX, UINT_MAX, 2);

  base::DictValue to_set;
  to_set.Set("a", byte_value_1_.Clone());
  to_set.Set("b", byte_value_16_.Clone());
  EXPECT_TRUE(storage_->Set(DEFAULTS, to_set).status().ok());
  settings.Set("a", byte_value_1_.Clone());
  settings.Set("b", byte_value_16_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  // Should be able to set existing keys to other values without going over
  // quota.
  to_set.Set("a", byte_value_16_.Clone());
  EXPECT_TRUE(storage_->Set(DEFAULTS, to_set).status().ok());
  settings.Set("a", byte_value_16_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  EXPECT_FALSE(storage_->Set(DEFAULTS, "c", byte_value_256_).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, RemovingExistingSettings) {
  base::DictValue settings;
  CreateStorage(266, UINT_MAX, 2);

  storage_->Set(DEFAULTS, "b", byte_value_16_);
  settings.Set("b", byte_value_16_.Clone());
  // Not enough quota.
  storage_->Set(DEFAULTS, "c", byte_value_256_);
  EXPECT_TRUE(SettingsEqual(settings));

  // Try again with "b" removed, enough quota.
  EXPECT_TRUE(storage_->Remove("b").status().ok());
  settings.Remove("b");
  EXPECT_TRUE(storage_->Set(DEFAULTS, "c", byte_value_256_).status().ok());
  settings.Set("c", byte_value_256_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  // Enough byte quota but max keys not high enough.
  EXPECT_TRUE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  settings.Set("a", byte_value_1_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  EXPECT_FALSE(storage_->Set(DEFAULTS, "b", byte_value_1_).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));

  // Back under max keys.
  EXPECT_TRUE(storage_->Remove("a").status().ok());
  settings.Remove("a");
  EXPECT_TRUE(storage_->Set(DEFAULTS, "b", byte_value_1_).status().ok());
  settings.Set("b", byte_value_1_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, RemovingNonexistentSettings) {
  base::DictValue settings;
  CreateStorage(36, UINT_MAX, 3);

  // Max out bytes.
  base::DictValue to_set;
  to_set.Set("b1", byte_value_16_.Clone());
  to_set.Set("b2", byte_value_16_.Clone());
  storage_->Set(DEFAULTS, to_set);
  settings.Set("b1", byte_value_16_.Clone());
  settings.Set("b2", byte_value_16_.Clone());
  EXPECT_FALSE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));

  // Remove some settings that don't exist.
  std::vector<std::string> to_remove;
  to_remove.push_back("a1");
  to_remove.push_back("a2");
  EXPECT_TRUE(storage_->Remove(to_remove).status().ok());
  EXPECT_TRUE(storage_->Remove("b").status().ok());
  EXPECT_TRUE(SettingsEqual(settings));

  // Still no quota.
  EXPECT_FALSE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));

  // Max out key count.
  to_set.clear();
  to_set.Set("b1", byte_value_1_.Clone());
  to_set.Set("b2", byte_value_1_.Clone());
  storage_->Set(DEFAULTS, to_set);
  settings.Set("b1", byte_value_1_.Clone());
  settings.Set("b2", byte_value_1_.Clone());
  storage_->Set(DEFAULTS, "b3", byte_value_1_);
  settings.Set("b3", byte_value_1_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  // Remove some settings that don't exist.
  to_remove.clear();
  to_remove.push_back("a1");
  to_remove.push_back("a2");
  EXPECT_TRUE(storage_->Remove(to_remove).status().ok());
  EXPECT_TRUE(storage_->Remove("b").status().ok());
  EXPECT_TRUE(SettingsEqual(settings));

  // Still no quota.
  EXPECT_FALSE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, Clear) {
  base::DictValue settings;
  CreateStorage(40, UINT_MAX, 5);

  // Test running out of byte quota.
  {
    base::DictValue to_set;
    to_set.Set("a", byte_value_16_.Clone());
    to_set.Set("b", byte_value_16_.Clone());
    EXPECT_TRUE(storage_->Set(DEFAULTS, to_set).status().ok());
    EXPECT_FALSE(storage_->Set(DEFAULTS, "c", byte_value_16_).status().ok());

    EXPECT_TRUE(storage_->Clear().status().ok());

    // (repeat)
    EXPECT_TRUE(storage_->Set(DEFAULTS, to_set).status().ok());
    EXPECT_FALSE(storage_->Set(DEFAULTS, "c", byte_value_16_).status().ok());
  }

  // Test reaching max keys.
  storage_->Clear();
  {
    base::DictValue to_set;
    to_set.Set("a", byte_value_1_.Clone());
    to_set.Set("b", byte_value_1_.Clone());
    to_set.Set("c", byte_value_1_.Clone());
    to_set.Set("d", byte_value_1_.Clone());
    to_set.Set("e", byte_value_1_.Clone());
    EXPECT_TRUE(storage_->Set(DEFAULTS, to_set).status().ok());
    EXPECT_FALSE(storage_->Set(DEFAULTS, "f", byte_value_1_).status().ok());

    storage_->Clear();

    // (repeat)
    EXPECT_TRUE(storage_->Set(DEFAULTS, to_set).status().ok());
    EXPECT_FALSE(storage_->Set(DEFAULTS, "f", byte_value_1_).status().ok());
  }
}

TEST_F(ExtensionSettingsQuotaTest, ChangingUsedBytesWithSet) {
  base::DictValue settings;
  CreateStorage(20, UINT_MAX, UINT_MAX);

  // Change a setting to make it go over quota.
  storage_->Set(DEFAULTS, "a", byte_value_16_);
  settings.Set("a", byte_value_16_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  EXPECT_FALSE(storage_->Set(DEFAULTS, "a", byte_value_256_).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));

  // Change a setting to reduce usage and room for another setting.
  EXPECT_FALSE(storage_->Set(DEFAULTS, "foobar", byte_value_1_).status().ok());
  storage_->Set(DEFAULTS, "a", byte_value_1_);
  settings.Set("a", byte_value_1_.Clone());

  EXPECT_TRUE(storage_->Set(DEFAULTS, "foobar", byte_value_1_).status().ok());
  settings.Set("foobar", byte_value_1_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, SetsOnlyEntirelyCompletedWithByteQuota) {
  base::DictValue settings;
  CreateStorage(40, UINT_MAX, UINT_MAX);

  storage_->Set(DEFAULTS, "a", byte_value_16_);
  settings.Set("a", byte_value_16_.Clone());

  // The entire change is over quota.
  base::DictValue to_set;
  to_set.Set("b", byte_value_16_.Clone());
  to_set.Set("c", byte_value_16_.Clone());
  EXPECT_FALSE(storage_->Set(DEFAULTS, to_set).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));

  // The entire change is over quota, but quota reduced in existing key.
  to_set.Set("a", byte_value_1_.Clone());
  EXPECT_TRUE(storage_->Set(DEFAULTS, to_set).status().ok());
  settings.Set("a", byte_value_1_.Clone());
  settings.Set("b", byte_value_16_.Clone());
  settings.Set("c", byte_value_16_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, SetsOnlyEntireCompletedWithMaxKeys) {
  base::DictValue settings;
  CreateStorage(UINT_MAX, UINT_MAX, 2);

  storage_->Set(DEFAULTS, "a", byte_value_1_);
  settings.Set("a", byte_value_1_.Clone());

  base::DictValue to_set;
  to_set.Set("b", byte_value_16_.Clone());
  to_set.Set("c", byte_value_16_.Clone());
  EXPECT_FALSE(storage_->Set(DEFAULTS, to_set).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, WithInitialDataAndByteQuota) {
  base::DictValue settings;
  delegate_->Set(DEFAULTS, "a", byte_value_256_);
  settings.Set("a", byte_value_256_.Clone());

  CreateStorage(280, UINT_MAX, UINT_MAX);
  EXPECT_TRUE(SettingsEqual(settings));

  // Add some data.
  EXPECT_TRUE(storage_->Set(DEFAULTS, "b", byte_value_16_).status().ok());
  settings.Set("b", byte_value_16_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  // Not enough quota.
  EXPECT_FALSE(storage_->Set(DEFAULTS, "c", byte_value_16_).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));

  // Reduce usage of original setting so that "c" can fit.
  EXPECT_TRUE(storage_->Set(DEFAULTS, "a", byte_value_16_).status().ok());
  settings.Set("a", byte_value_16_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  EXPECT_TRUE(storage_->Set(DEFAULTS, "c", byte_value_16_).status().ok());
  settings.Set("c", byte_value_16_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  // Remove to free up some more data.
  EXPECT_FALSE(storage_->Set(DEFAULTS, "d", byte_value_256_).status().ok());

  std::vector<std::string> to_remove;
  to_remove.push_back("a");
  to_remove.push_back("b");
  storage_->Remove(to_remove);
  settings.Remove("a");
  settings.Remove("b");
  EXPECT_TRUE(SettingsEqual(settings));

  EXPECT_TRUE(storage_->Set(DEFAULTS, "d", byte_value_256_).status().ok());
  settings.Set("d", byte_value_256_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, WithInitialDataAndMaxKeys) {
  base::DictValue settings;
  delegate_->Set(DEFAULTS, "a", byte_value_1_);
  settings.Set("a", byte_value_1_.Clone());
  CreateStorage(UINT_MAX, UINT_MAX, 2);

  EXPECT_TRUE(storage_->Set(DEFAULTS, "b", byte_value_1_).status().ok());
  settings.Set("b", byte_value_1_.Clone());

  EXPECT_FALSE(storage_->Set(DEFAULTS, "c", byte_value_1_).status().ok());

  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, InitiallyOverByteQuota) {
  base::DictValue settings;
  settings.Set("a", byte_value_16_.Clone());
  settings.Set("b", byte_value_16_.Clone());
  settings.Set("c", byte_value_16_.Clone());
  delegate_->Set(DEFAULTS, settings);

  CreateStorage(40, UINT_MAX, UINT_MAX);
  EXPECT_TRUE(SettingsEqual(settings));

  EXPECT_FALSE(storage_->Set(DEFAULTS, "d", byte_value_16_).status().ok());

  // Take under quota by reducing size of an existing setting
  EXPECT_TRUE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  settings.Set("a", byte_value_1_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  // Should be able set another small setting.
  EXPECT_TRUE(storage_->Set(DEFAULTS, "d", byte_value_1_).status().ok());
  settings.Set("d", byte_value_1_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, InitiallyOverMaxKeys) {
  base::DictValue settings;
  settings.Set("a", byte_value_16_.Clone());
  settings.Set("b", byte_value_16_.Clone());
  settings.Set("c", byte_value_16_.Clone());
  delegate_->Set(DEFAULTS, settings);

  CreateStorage(UINT_MAX, UINT_MAX, 2);
  EXPECT_TRUE(SettingsEqual(settings));

  // Can't set either an existing or new setting.
  EXPECT_FALSE(storage_->Set(DEFAULTS, "d", byte_value_16_).status().ok());
  EXPECT_FALSE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));

  // Should be able after removing 2.
  storage_->Remove("a");
  settings.Remove("a");
  storage_->Remove("b");
  settings.Remove("b");
  EXPECT_TRUE(SettingsEqual(settings));

  EXPECT_TRUE(storage_->Set(DEFAULTS, "e", byte_value_1_).status().ok());
  settings.Set("e", byte_value_1_.Clone());
  EXPECT_TRUE(SettingsEqual(settings));

  // Still can't set any.
  EXPECT_FALSE(storage_->Set(DEFAULTS, "d", byte_value_16_).status().ok());
  EXPECT_FALSE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, ZeroQuotaBytesPerSetting) {
  base::DictValue empty;
  CreateStorage(UINT_MAX, 0, UINT_MAX);

  EXPECT_FALSE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  EXPECT_TRUE(storage_->Remove("a").status().ok());
  EXPECT_TRUE(storage_->Remove("b").status().ok());
  EXPECT_TRUE(SettingsEqual(empty));
}

TEST_F(ExtensionSettingsQuotaTest, QuotaBytesPerSetting) {
  base::DictValue settings;

  CreateStorage(UINT_MAX, 20, UINT_MAX);

  EXPECT_TRUE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  EXPECT_TRUE(storage_->Set(DEFAULTS, "a", byte_value_16_).status().ok());
  settings.Set("a", byte_value_16_.Clone());
  EXPECT_FALSE(storage_->Set(DEFAULTS, "a", byte_value_256_).status().ok());

  EXPECT_TRUE(storage_->Set(DEFAULTS, "b", byte_value_1_).status().ok());
  EXPECT_TRUE(storage_->Set(DEFAULTS, "b", byte_value_16_).status().ok());
  settings.Set("b", byte_value_16_.Clone());
  EXPECT_FALSE(storage_->Set(DEFAULTS, "b", byte_value_256_).status().ok());

  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, QuotaBytesPerSettingWithInitialSettings) {
  base::DictValue settings;

  delegate_->Set(DEFAULTS, "a", byte_value_1_);
  delegate_->Set(DEFAULTS, "b", byte_value_16_);
  delegate_->Set(DEFAULTS, "c", byte_value_256_);
  CreateStorage(UINT_MAX, 20, UINT_MAX);

  EXPECT_TRUE(storage_->Set(DEFAULTS, "a", byte_value_1_).status().ok());
  EXPECT_TRUE(storage_->Set(DEFAULTS, "a", byte_value_16_).status().ok());
  settings.Set("a", byte_value_16_.Clone());
  EXPECT_FALSE(storage_->Set(DEFAULTS, "a", byte_value_256_).status().ok());

  EXPECT_TRUE(storage_->Set(DEFAULTS, "b", byte_value_1_).status().ok());
  EXPECT_TRUE(storage_->Set(DEFAULTS, "b", byte_value_16_).status().ok());
  settings.Set("b", byte_value_16_.Clone());
  EXPECT_FALSE(storage_->Set(DEFAULTS, "b", byte_value_256_).status().ok());

  EXPECT_TRUE(storage_->Set(DEFAULTS, "c", byte_value_1_).status().ok());
  EXPECT_TRUE(storage_->Set(DEFAULTS, "c", byte_value_16_).status().ok());
  settings.Set("c", byte_value_16_.Clone());
  EXPECT_FALSE(storage_->Set(DEFAULTS, "c", byte_value_256_).status().ok());

  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest,
    QuotaBytesPerSettingWithInitialSettingsForced) {
  // This is a lazy test to make sure IGNORE_QUOTA lets through changes: the
  // test above copied, but using IGNORE_QUOTA and asserting nothing is ever
  // rejected...
  base::DictValue settings;

  delegate_->Set(DEFAULTS, "a", byte_value_1_);
  delegate_->Set(DEFAULTS, "b", byte_value_16_);
  delegate_->Set(DEFAULTS, "c", byte_value_256_);
  CreateStorage(UINT_MAX, 20, UINT_MAX);

  EXPECT_TRUE(storage_->Set(IGNORE_QUOTA, "a", byte_value_1_).status().ok());
  EXPECT_TRUE(storage_->Set(IGNORE_QUOTA, "a", byte_value_16_).status().ok());
  EXPECT_TRUE(storage_->Set(IGNORE_QUOTA, "a", byte_value_256_).status().ok());
  settings.Set("a", byte_value_256_.Clone());

  EXPECT_TRUE(storage_->Set(IGNORE_QUOTA, "b", byte_value_1_).status().ok());
  EXPECT_TRUE(storage_->Set(IGNORE_QUOTA, "b", byte_value_16_).status().ok());
  EXPECT_TRUE(storage_->Set(IGNORE_QUOTA, "b", byte_value_256_).status().ok());
  settings.Set("b", byte_value_256_.Clone());

  EXPECT_TRUE(storage_->Set(IGNORE_QUOTA, "c", byte_value_1_).status().ok());
  EXPECT_TRUE(storage_->Set(IGNORE_QUOTA, "c", byte_value_16_).status().ok());
  settings.Set("c", byte_value_16_.Clone());

  // ... except the last.  Make sure it can still fail.
  EXPECT_FALSE(storage_->Set(DEFAULTS, "c", byte_value_256_).status().ok());

  EXPECT_TRUE(SettingsEqual(settings));
}

TEST_F(ExtensionSettingsQuotaTest, GetBytesInUse) {
  // Just testing GetBytesInUse, no need for a quota.
  CreateStorage(UINT_MAX, UINT_MAX, UINT_MAX);

  std::vector<std::string> ab;
  ab.push_back("a");
  ab.push_back("b");

  EXPECT_EQ(0u, storage_->GetBytesInUse());
  EXPECT_EQ(0u, storage_->GetBytesInUse("a"));
  EXPECT_EQ(0u, storage_->GetBytesInUse("b"));
  EXPECT_EQ(0u, storage_->GetBytesInUse(ab));

  storage_->Set(DEFAULTS, "a", byte_value_1_);

  EXPECT_EQ(2u, storage_->GetBytesInUse());
  EXPECT_EQ(2u, storage_->GetBytesInUse("a"));
  EXPECT_EQ(0u, storage_->GetBytesInUse("b"));
  EXPECT_EQ(2u, storage_->GetBytesInUse(ab));

  storage_->Set(DEFAULTS, "b", byte_value_1_);

  EXPECT_EQ(4u, storage_->GetBytesInUse());
  EXPECT_EQ(2u, storage_->GetBytesInUse("a"));
  EXPECT_EQ(2u, storage_->GetBytesInUse("b"));
  EXPECT_EQ(4u, storage_->GetBytesInUse(ab));

  storage_->Set(DEFAULTS, "c", byte_value_1_);

  EXPECT_EQ(6u, storage_->GetBytesInUse());
  EXPECT_EQ(2u, storage_->GetBytesInUse("a"));
  EXPECT_EQ(2u, storage_->GetBytesInUse("b"));
  EXPECT_EQ(4u, storage_->GetBytesInUse(ab));
}

}  // namespace extensions
