| Index: chrome/browser/extensions/extension_settings_storage_unittest.cc
|
| diff --git a/chrome/browser/extensions/extension_settings_storage_unittest.cc b/chrome/browser/extensions/extension_settings_storage_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b8c8580627445ae8774d93e6b14d9b817ddb4c80
|
| --- /dev/null
|
| +++ b/chrome/browser/extensions/extension_settings_storage_unittest.cc
|
| @@ -0,0 +1,386 @@
|
| +// Copyright (c) 2011 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.
|
| +
|
| +// TODO(kalman): More tests:
|
| +// - Keys/values containing dots.
|
| +// - More than one active settings object.
|
| +// - Failure cases.
|
| +// - Test with existing data (i.e. shut down leveldb storage, re-start).
|
| +
|
| +#include "chrome/browser/extensions/extension_settings_storage_unittest.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/json/json_writer.h"
|
| +#include "base/file_util.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "base/message_loop.h"
|
| +#include "base/values.h"
|
| +#include "chrome/browser/extensions/extension_settings.h"
|
| +#include "content/browser/browser_thread.h"
|
| +
|
| +// Define macro to get the __LINE__ expansion.
|
| +#define newCallback(expected) (new AssertEqualsCallback((expected), __LINE__))
|
| +
|
| +namespace {
|
| +
|
| +// Callback from GetStorage() that places the new storage in a given location.
|
| +class GetStorageCallback {
|
| + public:
|
| + explicit GetStorageCallback(ExtensionSettingsStorage** storagePtr)
|
| + : storagePtr_(storagePtr) {
|
| + *storagePtr = NULL;
|
| + }
|
| +
|
| + void Run(ExtensionSettingsStorage* storage) {
|
| + DCHECK(*storagePtr_ == NULL);
|
| + *storagePtr_ = storage;
|
| + delete this;
|
| + }
|
| +
|
| + private:
|
| + ExtensionSettingsStorage** storagePtr_;
|
| +};
|
| +
|
| +// Callback from storage methods which performs the test assertions.
|
| +class AssertEqualsCallback : public ExtensionSettingsStorage::Callback {
|
| + public:
|
| + AssertEqualsCallback(DictionaryValue* expected, int line)
|
| + : expected_(expected), line_(line), called_(false) {
|
| + }
|
| +
|
| + ~AssertEqualsCallback() {
|
| + // Need to DCHECK since ASSERT_* can't be used from destructors.
|
| + DCHECK(called_);
|
| + }
|
| +
|
| + virtual void OnSuccess(DictionaryValue* actual) OVERRIDE {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + ASSERT_FALSE(called_) << "Callback has already been called";
|
| + called_ = true;
|
| + ASSERT_TRUE(expected_->Equals(actual)) << "Values are different:\n" <<
|
| + "Line: " << line_ << "\n" <<
|
| + "Expected: " << GetJson(expected_) <<
|
| + "Got: " << GetJson(actual);
|
| + delete actual;
|
| + }
|
| +
|
| + virtual void OnFailure(const std::string& message) OVERRIDE {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + ASSERT_FALSE(called_) << "Callback has already been called";
|
| + called_ = true;
|
| + // No tests allow failure (yet).
|
| + ASSERT_TRUE(false) << "Callback failed on line " << line_;
|
| + }
|
| +
|
| + private:
|
| + std::string GetJson(Value* value) {
|
| + std::string json;
|
| + base::JSONWriter::Write(value, true, &json);
|
| + return json;
|
| + }
|
| +
|
| + DictionaryValue* expected_;
|
| + int line_;
|
| + bool called_;
|
| +};
|
| +
|
| +std::string key1() {
|
| + return "foo";
|
| +}
|
| +
|
| +std::string key2() {
|
| + return "bar";
|
| +}
|
| +
|
| +std::string key3() {
|
| + return "baz";
|
| +}
|
| +
|
| +Value* val1() {
|
| + Value* val = NULL;
|
| + if (val == NULL) {
|
| + val = Value::CreateStringValue(key1() + "Value");
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +Value* val2() {
|
| + static Value* val = NULL;
|
| + if (val == NULL) {
|
| + val = Value::CreateStringValue(key2() + "Value");
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +Value* val3() {
|
| + static Value* val = NULL;
|
| + if (val == NULL) {
|
| + val = Value::CreateStringValue(key3() + "Value");
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +ListValue* emptyList() {
|
| + static ListValue* val = NULL;
|
| + if (val == NULL) {
|
| + val = new ListValue();
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +ListValue* list1() {
|
| + static ListValue* val = NULL;
|
| + if (val == NULL) {
|
| + val = new ListValue();
|
| + val->Append(Value::CreateStringValue(key1()));
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +ListValue* list2() {
|
| + static ListValue* val = NULL;
|
| + if (val == NULL) {
|
| + val = new ListValue();
|
| + val->Append(Value::CreateStringValue(key2()));
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +ListValue* list12() {
|
| + static ListValue* val = NULL;
|
| + if (val == NULL) {
|
| + val = new ListValue();
|
| + val->Append(Value::CreateStringValue(key1()));
|
| + val->Append(Value::CreateStringValue(key2()));
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +ListValue* list13() {
|
| + static ListValue* val = NULL;
|
| + if (val == NULL) {
|
| + val = new ListValue();
|
| + val->Append(Value::CreateStringValue(key1()));
|
| + val->Append(Value::CreateStringValue(key3()));
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +ListValue* list123() {
|
| + static ListValue* val = NULL;
|
| + if (val == NULL) {
|
| + val = new ListValue();
|
| + val->Append(Value::CreateStringValue(key1()));
|
| + val->Append(Value::CreateStringValue(key2()));
|
| + val->Append(Value::CreateStringValue(key3()));
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +DictionaryValue* emptyDict() {
|
| + static DictionaryValue* val = NULL;
|
| + if (val == NULL) {
|
| + val = new DictionaryValue();
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +DictionaryValue* dict1() {
|
| + static DictionaryValue* val = NULL;
|
| + if (val == NULL) {
|
| + val = new DictionaryValue();
|
| + val->Set(key1(), val1()->DeepCopy());
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +DictionaryValue* dict12() {
|
| + static DictionaryValue* val = NULL;
|
| + if (val == NULL) {
|
| + val = new DictionaryValue();
|
| + val->Set(key1(), val1()->DeepCopy());
|
| + val->Set(key2(), val2()->DeepCopy());
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +DictionaryValue* dict123() {
|
| + static DictionaryValue* val = NULL;
|
| + if (val == NULL) {
|
| + val = new DictionaryValue();
|
| + val->Set(key1(), val1()->DeepCopy());
|
| + val->Set(key2(), val2()->DeepCopy());
|
| + val->Set(key3(), val3()->DeepCopy());
|
| + }
|
| + return val;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +void ExtensionSettingsStorageTest::SetUp() {
|
| + ui_message_loop_ = new MessageLoopForUI();
|
| + // Use the same message loop for the UI and FILE threads, giving a test
|
| + // pattern where storage API calls get posted to the same message loop (the
|
| + // current one), then all run with MessageLoop::current()->RunAllPending().
|
| + ui_thread_ = new BrowserThread(BrowserThread::UI, MessageLoop::current());
|
| + file_thread_ = new BrowserThread(BrowserThread::FILE, MessageLoop::current());
|
| +
|
| + FilePath temp_dir;
|
| + file_util::CreateNewTempDirectory(FilePath::StringType(), &temp_dir);
|
| + settings_ = new ExtensionSettings(temp_dir);
|
| +
|
| + storage_ = NULL;
|
| + (GetParam())(
|
| + settings_,
|
| + "fakeExtension",
|
| + base::Bind(
|
| + &GetStorageCallback::Run,
|
| + base::Unretained(new GetStorageCallback(&storage_))));
|
| + MessageLoop::current()->RunAllPending();
|
| + DCHECK(storage_ != NULL);
|
| +}
|
| +
|
| +void ExtensionSettingsStorageTest::TearDown() {
|
| + delete settings_;
|
| + delete file_thread_;
|
| + delete ui_thread_;
|
| + delete ui_message_loop_;
|
| +}
|
| +
|
| +TEST_P(ExtensionSettingsStorageTest, GetWhenEmpty) {
|
| + storage_->Get(key1(), newCallback(emptyDict()));
|
| + storage_->Get(key2(), newCallback(emptyDict()));
|
| + storage_->Get(key3(), newCallback(emptyDict()));
|
| + storage_->Get(*emptyList(), newCallback(emptyDict()));
|
| + storage_->Get(*list1(), newCallback(emptyDict()));
|
| + storage_->Get(*list123(), newCallback(emptyDict()));
|
| + storage_->Get(newCallback(emptyDict()));
|
| + MessageLoop::current()->RunAllPending();
|
| +}
|
| +
|
| +TEST_P(ExtensionSettingsStorageTest, GetWithSingleValue) {
|
| + storage_->Set(key1(), *val1(), newCallback(dict1()));
|
| + MessageLoop::current()->RunAllPending();
|
| +
|
| + storage_->Get(key1(), newCallback(dict1()));
|
| + storage_->Get(key2(), newCallback(emptyDict()));
|
| + storage_->Get(key3(), newCallback(emptyDict()));
|
| + storage_->Get(*emptyList(), newCallback(emptyDict()));
|
| + storage_->Get(*list1(), newCallback(dict1()));
|
| + storage_->Get(*list2(), newCallback(emptyDict()));
|
| + storage_->Get(*list123(), newCallback(dict1()));
|
| + storage_->Get(newCallback(dict1()));
|
| + MessageLoop::current()->RunAllPending();
|
| +}
|
| +
|
| +TEST_P(ExtensionSettingsStorageTest, GetWithMultipleValues) {
|
| + storage_->Set(*dict12(), newCallback(dict12()));
|
| + MessageLoop::current()->RunAllPending();
|
| +
|
| + storage_->Get(key1(), newCallback(dict1()));
|
| + storage_->Get(key3(), newCallback(emptyDict()));
|
| + storage_->Get(*emptyList(), newCallback(emptyDict()));
|
| + storage_->Get(*list1(), newCallback(dict1()));
|
| + storage_->Get(*list13(), newCallback(dict1()));
|
| + storage_->Get(*list12(), newCallback(dict12()));
|
| + storage_->Get(*list123(), newCallback(dict12()));
|
| + storage_->Get(newCallback(dict12()));
|
| + MessageLoop::current()->RunAllPending();
|
| +}
|
| +
|
| +TEST_P(ExtensionSettingsStorageTest, RemoveWhenEmpty) {
|
| + storage_->Remove(key1(), newCallback(emptyDict()));
|
| + MessageLoop::current()->RunAllPending();
|
| +
|
| + storage_->Get(key1(), newCallback(emptyDict()));
|
| + storage_->Get(*list1(), newCallback(emptyDict()));
|
| + storage_->Get(newCallback(emptyDict()));
|
| + MessageLoop::current()->RunAllPending();
|
| +}
|
| +
|
| +TEST_P(ExtensionSettingsStorageTest, RemoveWithSingleValue) {
|
| + storage_->Set(key1(), *val1(), newCallback(dict1()));
|
| + MessageLoop::current()->RunAllPending();
|
| + storage_->Remove(key1(), newCallback(emptyDict()));
|
| + MessageLoop::current()->RunAllPending();
|
| +
|
| + storage_->Get(key1(), newCallback(emptyDict()));
|
| + storage_->Get(key2(), newCallback(emptyDict()));
|
| + storage_->Get(*list1(), newCallback(emptyDict()));
|
| + storage_->Get(*list12(), newCallback(emptyDict()));
|
| + storage_->Get(newCallback(emptyDict()));
|
| + MessageLoop::current()->RunAllPending();
|
| +}
|
| +
|
| +TEST_P(ExtensionSettingsStorageTest, RemoveWithMultipleValues) {
|
| + storage_->Set(*dict123(), newCallback(dict123()));
|
| + MessageLoop::current()->RunAllPending();
|
| + storage_->Remove(key3(), newCallback(emptyDict()));
|
| + MessageLoop::current()->RunAllPending();
|
| +
|
| + storage_->Get(key1(), newCallback(dict1()));
|
| + storage_->Get(key3(), newCallback(emptyDict()));
|
| + storage_->Get(*emptyList(), newCallback(emptyDict()));
|
| + storage_->Get(*list1(), newCallback(dict1()));
|
| + storage_->Get(*list13(), newCallback(dict1()));
|
| + storage_->Get(*list12(), newCallback(dict12()));
|
| + storage_->Get(*list123(), newCallback(dict12()));
|
| + storage_->Get(newCallback(dict12()));
|
| +
|
| + storage_->Remove(*list2(), newCallback(emptyDict()));
|
| + MessageLoop::current()->RunAllPending();
|
| +
|
| + storage_->Get(key1(), newCallback(dict1()));
|
| + storage_->Get(key2(), newCallback(emptyDict()));
|
| + storage_->Get(key3(), newCallback(emptyDict()));
|
| + storage_->Get(*emptyList(), newCallback(emptyDict()));
|
| + storage_->Get(*list1(), newCallback(dict1()));
|
| + storage_->Get(*list2(), newCallback(emptyDict()));
|
| + storage_->Get(*list123(), newCallback(dict1()));
|
| + storage_->Get(newCallback(dict1()));
|
| + MessageLoop::current()->RunAllPending();
|
| +}
|
| +
|
| +TEST_P(ExtensionSettingsStorageTest, SetWhenOverwriting) {
|
| + DictionaryValue key1Val2;
|
| + key1Val2.Set(key1(), val2()->DeepCopy());
|
| + storage_->Set(key1(), *val2(), newCallback(&key1Val2));
|
| + MessageLoop::current()->RunAllPending();
|
| +
|
| + storage_->Set(*dict12(), newCallback(dict12()));
|
| + MessageLoop::current()->RunAllPending();
|
| +
|
| + storage_->Get(key1(), newCallback(dict1()));
|
| + storage_->Get(key3(), newCallback(emptyDict()));
|
| + storage_->Get(*emptyList(), newCallback(emptyDict()));
|
| + storage_->Get(*list1(), newCallback(dict1()));
|
| + storage_->Get(*list13(), newCallback(dict1()));
|
| + storage_->Get(*list12(), newCallback(dict12()));
|
| + storage_->Get(*list123(), newCallback(dict12()));
|
| + storage_->Get(newCallback(dict12()));
|
| + MessageLoop::current()->RunAllPending();
|
| +}
|
| +
|
| +TEST_P(ExtensionSettingsStorageTest, ClearWhenEmpty) {
|
| + storage_->Clear(newCallback(emptyDict()));
|
| + MessageLoop::current()->RunAllPending();
|
| +
|
| + storage_->Get(key1(), newCallback(emptyDict()));
|
| + storage_->Get(*list1(), newCallback(emptyDict()));
|
| + storage_->Get(newCallback(emptyDict()));
|
| + MessageLoop::current()->RunAllPending();
|
| +}
|
| +
|
| +TEST_P(ExtensionSettingsStorageTest, ClearWhenNotEmpty) {
|
| + storage_->Set(*dict12(), newCallback(dict12()));
|
| + MessageLoop::current()->RunAllPending();
|
| +
|
| + storage_->Clear(newCallback(emptyDict()));
|
| + MessageLoop::current()->RunAllPending();
|
| +
|
| + storage_->Get(key1(), newCallback(emptyDict()));
|
| + storage_->Get(*list1(), newCallback(emptyDict()));
|
| + storage_->Get(newCallback(emptyDict()));
|
| + MessageLoop::current()->RunAllPending();
|
| +}
|
|
|