Index: base/prefs/json_pref_store_unittest.cc |
diff --git a/base/prefs/json_pref_store_unittest.cc b/base/prefs/json_pref_store_unittest.cc |
index f4e1e5190dd903bb4c69ffab8f0d003106f987c0..4c9c847708f5f2d3f9845759bfffb7598b68e832 100644 |
--- a/base/prefs/json_pref_store_unittest.cc |
+++ b/base/prefs/json_pref_store_unittest.cc |
@@ -4,10 +4,12 @@ |
#include "base/prefs/json_pref_store.h" |
+#include "base/bind.h" |
#include "base/file_util.h" |
#include "base/files/scoped_temp_dir.h" |
#include "base/memory/ref_counted.h" |
#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop/message_loop.h" |
#include "base/path_service.h" |
#include "base/prefs/pref_filter.h" |
#include "base/run_loop.h" |
@@ -25,6 +27,50 @@ namespace { |
const char kHomePage[] = "homepage"; |
+// A PrefFilter that will intercept all calls to FilterOnLoad() and hold on |
+// to the |prefs| until explicitly asked to release them. |
+class InterceptingPrefFilter : public PrefFilter { |
+ public: |
+ InterceptingPrefFilter(); |
+ virtual ~InterceptingPrefFilter(); |
+ |
+ // PrefFilter implementation: |
+ virtual void FilterOnLoad( |
+ const PostFilterOnLoadCallback& post_filter_on_load_callback, |
+ scoped_ptr<base::DictionaryValue> pref_store_contents) OVERRIDE; |
+ virtual void FilterUpdate(const std::string& path) OVERRIDE {} |
+ virtual void FilterSerializeData( |
+ const base::DictionaryValue* pref_store_contents) OVERRIDE {} |
+ |
+ bool has_intercepted_prefs() const { return intercepted_prefs_ != NULL; } |
+ |
+ // Finalize an intercepted read, handing |intercept_prefs_| back to its |
+ // JsonPrefStore. |
+ void ReleasePrefs(); |
+ |
+ private: |
+ PostFilterOnLoadCallback post_filter_on_load_callback_; |
+ scoped_ptr<base::DictionaryValue> intercepted_prefs_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(InterceptingPrefFilter); |
+}; |
+ |
+InterceptingPrefFilter::InterceptingPrefFilter() {} |
+InterceptingPrefFilter::~InterceptingPrefFilter() {} |
+ |
+void InterceptingPrefFilter::FilterOnLoad( |
+ const PostFilterOnLoadCallback& post_filter_on_load_callback, |
+ scoped_ptr<base::DictionaryValue> pref_store_contents) { |
+ post_filter_on_load_callback_ = post_filter_on_load_callback; |
+ intercepted_prefs_ = pref_store_contents.Pass(); |
+} |
+ |
+void InterceptingPrefFilter::ReleasePrefs() { |
+ EXPECT_FALSE(post_filter_on_load_callback_.is_null()); |
+ post_filter_on_load_callback_.Run(intercepted_prefs_.Pass(), false); |
+ post_filter_on_load_callback_.Reset(); |
+} |
+ |
class MockPrefStoreObserver : public PrefStore::Observer { |
public: |
MOCK_METHOD1(OnPrefValueChanged, void (const std::string&)); |
@@ -48,6 +94,13 @@ class JsonPrefStoreTest : public testing::Test { |
ASSERT_TRUE(PathExists(data_dir_)); |
} |
+ virtual void TearDown() OVERRIDE { |
+ // Make sure all pending tasks have been processed (e.g., deleting the |
+ // JsonPrefStore may post write tasks). |
+ message_loop_.PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure()); |
+ message_loop_.Run(); |
+ } |
+ |
// The path to temporary directory used to contain the test operations. |
base::ScopedTempDir temp_dir_; |
// The path to the directory where the test data is stored. |
@@ -157,7 +210,7 @@ void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store, |
TEST_F(JsonPrefStoreTest, Basic) { |
ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"), |
- temp_dir_.path().AppendASCII("write.json"))); |
+ temp_dir_.path().AppendASCII("write.json"))); |
// Test that the persistent value can be loaded. |
base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); |
@@ -167,7 +220,8 @@ TEST_F(JsonPrefStoreTest, Basic) { |
message_loop_.message_loop_proxy().get(), |
scoped_ptr<PrefFilter>()); |
ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs()); |
- ASSERT_FALSE(pref_store->ReadOnly()); |
+ EXPECT_FALSE(pref_store->ReadOnly()); |
+ EXPECT_TRUE(pref_store->IsInitializationComplete()); |
// The JSON file looks like this: |
// { |
@@ -185,7 +239,7 @@ TEST_F(JsonPrefStoreTest, Basic) { |
TEST_F(JsonPrefStoreTest, BasicAsync) { |
ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"), |
- temp_dir_.path().AppendASCII("write.json"))); |
+ temp_dir_.path().AppendASCII("write.json"))); |
// Test that the persistent value can be loaded. |
base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); |
@@ -208,7 +262,8 @@ TEST_F(JsonPrefStoreTest, BasicAsync) { |
RunLoop().RunUntilIdle(); |
pref_store->RemoveObserver(&mock_observer); |
- ASSERT_FALSE(pref_store->ReadOnly()); |
+ EXPECT_FALSE(pref_store->ReadOnly()); |
+ EXPECT_TRUE(pref_store->IsInitializationComplete()); |
} |
// The JSON file looks like this: |
@@ -301,4 +356,117 @@ TEST_F(JsonPrefStoreTest, AsyncNonExistingFile) { |
EXPECT_FALSE(pref_store->ReadOnly()); |
} |
+TEST_F(JsonPrefStoreTest, ReadWithInterceptor) { |
+ ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"), |
+ temp_dir_.path().AppendASCII("write.json"))); |
+ |
+ // Test that the persistent value can be loaded. |
+ base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); |
+ ASSERT_TRUE(PathExists(input_file)); |
+ |
+ scoped_ptr<InterceptingPrefFilter> intercepting_pref_filter( |
+ new InterceptingPrefFilter()); |
+ InterceptingPrefFilter* raw_intercepting_pref_filter_ = |
+ intercepting_pref_filter.get(); |
+ scoped_refptr<JsonPrefStore> pref_store = |
+ new JsonPrefStore(input_file, |
+ message_loop_.message_loop_proxy().get(), |
+ intercepting_pref_filter.PassAs<PrefFilter>()); |
+ |
+ ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE, |
+ pref_store->ReadPrefs()); |
+ EXPECT_FALSE(pref_store->ReadOnly()); |
+ |
+ // The store shouldn't be considered initialized until the interceptor |
+ // returns. |
+ EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs()); |
+ EXPECT_FALSE(pref_store->IsInitializationComplete()); |
+ EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL)); |
+ |
+ raw_intercepting_pref_filter_->ReleasePrefs(); |
+ |
+ EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs()); |
+ EXPECT_TRUE(pref_store->IsInitializationComplete()); |
+ EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL)); |
+ |
+ // The JSON file looks like this: |
+ // { |
+ // "homepage": "http://www.cnn.com", |
+ // "some_directory": "/usr/local/", |
+ // "tabs": { |
+ // "new_windows_in_tabs": true, |
+ // "max_tabs": 20 |
+ // } |
+ // } |
+ |
+ RunBasicJsonPrefStoreTest( |
+ pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json")); |
+} |
+ |
+TEST_F(JsonPrefStoreTest, ReadAsyncWithInterceptor) { |
+ ASSERT_TRUE(base::CopyFile(data_dir_.AppendASCII("read.json"), |
+ temp_dir_.path().AppendASCII("write.json"))); |
+ |
+ // Test that the persistent value can be loaded. |
+ base::FilePath input_file = temp_dir_.path().AppendASCII("write.json"); |
+ ASSERT_TRUE(PathExists(input_file)); |
+ |
+ scoped_ptr<InterceptingPrefFilter> intercepting_pref_filter( |
+ new InterceptingPrefFilter()); |
+ InterceptingPrefFilter* raw_intercepting_pref_filter_ = |
+ intercepting_pref_filter.get(); |
+ scoped_refptr<JsonPrefStore> pref_store = |
+ new JsonPrefStore(input_file, |
+ message_loop_.message_loop_proxy().get(), |
+ intercepting_pref_filter.PassAs<PrefFilter>()); |
+ |
+ MockPrefStoreObserver mock_observer; |
+ pref_store->AddObserver(&mock_observer); |
+ |
+ // Ownership of the |mock_error_delegate| is handed to the |pref_store| below. |
+ MockReadErrorDelegate* mock_error_delegate = new MockReadErrorDelegate; |
+ |
+ { |
+ pref_store->ReadPrefsAsync(mock_error_delegate); |
+ |
+ EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(0); |
+ // EXPECT_CALL(*mock_error_delegate, |
+ // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0); |
+ RunLoop().RunUntilIdle(); |
+ |
+ EXPECT_FALSE(pref_store->ReadOnly()); |
+ EXPECT_TRUE(raw_intercepting_pref_filter_->has_intercepted_prefs()); |
+ EXPECT_FALSE(pref_store->IsInitializationComplete()); |
+ EXPECT_FALSE(pref_store->GetValue(kHomePage, NULL)); |
+ } |
+ |
+ { |
+ EXPECT_CALL(mock_observer, OnInitializationCompleted(true)).Times(1); |
+ // EXPECT_CALL(*mock_error_delegate, |
+ // OnError(PersistentPrefStore::PREF_READ_ERROR_NONE)).Times(0); |
+ |
+ raw_intercepting_pref_filter_->ReleasePrefs(); |
+ |
+ EXPECT_FALSE(pref_store->ReadOnly()); |
+ EXPECT_FALSE(raw_intercepting_pref_filter_->has_intercepted_prefs()); |
+ EXPECT_TRUE(pref_store->IsInitializationComplete()); |
+ EXPECT_TRUE(pref_store->GetValue(kHomePage, NULL)); |
+ } |
+ |
+ pref_store->RemoveObserver(&mock_observer); |
+ |
+ // The JSON file looks like this: |
+ // { |
+ // "homepage": "http://www.cnn.com", |
+ // "some_directory": "/usr/local/", |
+ // "tabs": { |
+ // "new_windows_in_tabs": true, |
+ // "max_tabs": 20 |
+ // } |
+ // } |
+ |
+ RunBasicJsonPrefStoreTest( |
+ pref_store.get(), input_file, data_dir_.AppendASCII("write.golden.json")); |
+} |
+ |
} // namespace base |