Chromium Code Reviews| 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..3940ab6345c9fc9dfdaacd306b6c7ee752073811 |
| --- /dev/null |
| +++ b/chrome/browser/extensions/extension_settings_storage_unittest.cc |
| @@ -0,0 +1,430 @@ |
| +// 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 |
| + |
| +#include "chrome/browser/extensions/extension_settings_storage_unittest.h" |
| + |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/json/json_writer.h" |
| +#include "base/values.h" |
| +#include "chrome/browser/extensions/extension_settings.h" |
| + |
| +// Define macros for these to get the __LINE__ expansion. |
| +// Undefined at the end of the file. |
| +#define newCallback(expected) \ |
| + (new AssertEqualsCallback((expected), false, __LINE__)) |
| +#define newQuittingCallback(expected) \ |
| + (new AssertEqualsCallback((expected), true, __LINE__)) |
| + |
| +namespace { |
| + |
| +// Wait for the QuitTask on the current message loop. Converse of running a |
| +// storage function with a newQuittingCallback(). |
| +void waitForQuit() { |
| + MessageLoop::current()->Run(); |
|
dgrogan
2011/06/18 01:54:40
When do you use Run vs RunAllPending?
not at google - send to devlin
2011/06/20 05:33:11
I don't think RunAllPending would work, at least w
dgrogan
2011/06/21 02:36:05
Thanks for the good explanation.
not at google - send to devlin
2011/06/22 09:40:38
Ah, very nice. Thank you.
|
| +} |
| + |
| +// Callback from GetStorage() which places the new storage in a given location. |
| +// Posts a QuitTask to the current message loop when done. |
| +class GetStorageCallback : public ExtensionSettings::Callback { |
| + public: |
| + explicit GetStorageCallback(ExtensionSettingsStorage** storagePtr) |
| + : storagePtr_(storagePtr) { |
| + *storagePtr = NULL; |
| + } |
| + |
| + ~GetStorageCallback() {} |
| + |
| + void Run(ExtensionSettingsStorage* storage) { |
| + DCHECK(*storagePtr_ == NULL); |
| + *storagePtr_ = storage; |
| + MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
| + } |
| + |
| + private: |
| + ExtensionSettingsStorage** storagePtr_; |
| +}; |
| + |
| +// Callback from storage methods which performs the test assertions. |
| +class AssertEqualsCallback : public ExtensionSettingsStorage::Callback { |
| + public: |
| + AssertEqualsCallback(DictionaryValue* expected, bool quit_when_done, int line) |
| + : expected_(expected), quit_when_done_(quit_when_done), line_(line), |
| + called_(false) { |
| + } |
| + |
| + ~AssertEqualsCallback() { |
| + // Need to DCHECK since ASSERT_* can't be used from destructors. |
| + DCHECK(called_); |
| + } |
| + |
| + void OnSuccess(DictionaryValue* actual) { |
| + // Post quit task first so that it always runs even if the test fails. |
| + MaybePostQuitTask(); |
| + 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; |
| + } |
| + |
| + void OnFailure(const std::string& message) { |
| + // Post quit task first so that it always runs even if the test fails. |
| + MaybePostQuitTask(); |
| + 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; |
| + } |
| + |
| + void MaybePostQuitTask() { |
| + if (quit_when_done_) { |
| + MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
| + } |
| + } |
| + |
| + DictionaryValue* expected_; |
| + bool quit_when_done_; |
| + int line_; |
| + bool called_; |
| +}; |
| + |
| +class TestSettingsCallback : public ExtensionSettings::Callback { |
| + public: |
| + explicit TestSettingsCallback(ExtensionSettingsStorage** storagePtr) |
| + : storagePtr_(storagePtr) { |
| + *storagePtr_ = NULL; |
| + } |
| + |
| + void Run(ExtensionSettingsStorage* storage) { |
| + DCHECK(*storagePtr_ == NULL); |
| + DCHECK(storage != NULL); |
| + *storagePtr_ = storage; |
| + } |
| + |
| + private: |
| + ExtensionSettingsStorage** storagePtr_; |
| +}; |
| + |
| +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(); |
| + ui_thread_ = new BrowserThread(BrowserThread::UI, MessageLoop::current()); |
| + file_thread_ = new BrowserThread(BrowserThread::FILE); |
| + file_thread_->Start(); |
| + |
| + FilePath temp_dir; |
| + file_util::CreateNewTempDirectory("", &temp_dir); |
| + settings_ = new ExtensionSettings(temp_dir); |
| + |
| + storage_ = NULL; |
| + settings_->GetStorageForTesting(GetParam(), "fakeExtension", |
| + new GetStorageCallback(&storage_)); |
| + waitForQuit(); |
| + DCHECK(storage_ != NULL); |
| +} |
| + |
| +void ExtensionSettingsStorageTest::TearDown() { |
| + delete settings_; |
| + |
| + file_thread_->Stop(); |
| + 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(newQuittingCallback(emptyDict())); |
| + waitForQuit(); |
| +} |
| + |
| +TEST_P(ExtensionSettingsStorageTest, GetWithSingleValue) { |
| + storage_->Set(key1(), *val1(), newQuittingCallback(dict1())); |
| + waitForQuit(); |
| + |
| + 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(newQuittingCallback(dict1())); |
| + waitForQuit(); |
| +} |
| + |
| +TEST_P(ExtensionSettingsStorageTest, GetWithMultipleValues) { |
| + storage_->Set(*dict12(), newQuittingCallback(dict12())); |
| + waitForQuit(); |
| + |
| + 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(newQuittingCallback(dict12())); |
| + waitForQuit(); |
| +} |
| + |
| +TEST_P(ExtensionSettingsStorageTest, RemoveWhenEmpty) { |
| + storage_->Remove(key1(), newQuittingCallback(emptyDict())); |
| + waitForQuit(); |
| + |
| + storage_->Get(key1(), newCallback(emptyDict())); |
| + storage_->Get(*list1(), newCallback(emptyDict())); |
| + |
| + storage_->Get(newQuittingCallback(emptyDict())); |
| + waitForQuit(); |
| +} |
| + |
| +TEST_P(ExtensionSettingsStorageTest, RemoveWithSingleValue) { |
| + storage_->Set(key1(), *val1(), newQuittingCallback(dict1())); |
| + waitForQuit(); |
| + storage_->Remove(key1(), newQuittingCallback(emptyDict())); |
| + waitForQuit(); |
| + |
| + storage_->Get(key1(), newCallback(emptyDict())); |
| + storage_->Get(key2(), newCallback(emptyDict())); |
| + storage_->Get(*list1(), newCallback(emptyDict())); |
| + storage_->Get(*list12(), newCallback(emptyDict())); |
| + |
| + storage_->Get(newQuittingCallback(emptyDict())); |
| + waitForQuit(); |
| +} |
| + |
| +TEST_P(ExtensionSettingsStorageTest, RemoveWithMultipleValues) { |
| + storage_->Set(*dict123(), newQuittingCallback(dict123())); |
| + waitForQuit(); |
| + storage_->Remove(key3(), newQuittingCallback(emptyDict())); |
| + waitForQuit(); |
| + |
| + 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(), newQuittingCallback(emptyDict())); |
| + waitForQuit(); |
| + |
| + 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(newQuittingCallback(dict1())); |
| + waitForQuit(); |
| +} |
| + |
| +TEST_P(ExtensionSettingsStorageTest, SetWhenOverwriting) { |
| + DictionaryValue key1Val2; |
| + key1Val2.Set(key1(), val2()->DeepCopy()); |
| + storage_->Set(key1(), *val2(), newQuittingCallback(&key1Val2)); |
| + waitForQuit(); |
| + |
| + storage_->Set(*dict12(), newQuittingCallback(dict12())); |
| + waitForQuit(); |
| + |
| + 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(newQuittingCallback(dict12())); |
| + waitForQuit(); |
| +} |
| + |
| +TEST_P(ExtensionSettingsStorageTest, ClearWhenEmpty) { |
| + storage_->Clear(newQuittingCallback(emptyDict())); |
| + waitForQuit(); |
| + |
| + storage_->Get(key1(), newCallback(emptyDict())); |
| + storage_->Get(*list1(), newCallback(emptyDict())); |
| + |
| + storage_->Get(newQuittingCallback(emptyDict())); |
| + waitForQuit(); |
| +} |
| + |
| +TEST_P(ExtensionSettingsStorageTest, ClearWhenNotEmpty) { |
| + storage_->Set(*dict12(), newQuittingCallback(dict12())); |
| + waitForQuit(); |
| + storage_->Clear(newQuittingCallback(emptyDict())); |
| + waitForQuit(); |
| + |
| + storage_->Get(key1(), newCallback(emptyDict())); |
| + storage_->Get(*list1(), newCallback(emptyDict())); |
| + |
| + storage_->Get(newQuittingCallback(emptyDict())); |
| + waitForQuit(); |
| +} |
| + |
| +#undef newCallback |
| +#undef newQuittingCallback |