Index: components/prefs/json_pref_store_unittest.cc |
diff --git a/components/prefs/json_pref_store_unittest.cc b/components/prefs/json_pref_store_unittest.cc |
index 32e30ea4506ff27f3a038b9b426543d1a984ec8b..c0092363ada5a68a3e6bb3380f2626a8bda9ea87 100644 |
--- a/components/prefs/json_pref_store_unittest.cc |
+++ b/components/prefs/json_pref_store_unittest.cc |
@@ -26,6 +26,7 @@ |
#include "base/strings/utf_string_conversions.h" |
#include "base/test/histogram_tester.h" |
#include "base/test/simple_test_clock.h" |
+#include "base/threading/sequenced_task_runner_handle.h" |
#include "base/threading/sequenced_worker_pool.h" |
#include "base/threading/thread.h" |
#include "base/values.h" |
@@ -823,15 +824,13 @@ class JsonPrefStoreLossyWriteTest : public JsonPrefStoreTest { |
test_file_ = temp_dir_.path().AppendASCII("test.json"); |
} |
- // Creates a JsonPrefStore with the given |file_writer|. |
scoped_refptr<JsonPrefStore> CreatePrefStore() { |
return new JsonPrefStore(test_file_, message_loop_.task_runner(), |
std::unique_ptr<PrefFilter>()); |
} |
// Return the ImportantFileWriter for a given JsonPrefStore. |
- ImportantFileWriter* GetImportantFileWriter( |
- scoped_refptr<JsonPrefStore> pref_store) { |
+ ImportantFileWriter* GetImportantFileWriter(JsonPrefStore* pref_store) { |
return &(pref_store->writer_); |
} |
@@ -850,7 +849,7 @@ class JsonPrefStoreLossyWriteTest : public JsonPrefStoreTest { |
TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteBasic) { |
scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore(); |
- ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store); |
+ ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get()); |
// Set a normal pref and check that it gets scheduled to be written. |
ASSERT_FALSE(file_writer->HasPendingWrite()); |
@@ -896,7 +895,7 @@ TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteBasic) { |
TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossyFirst) { |
scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore(); |
- ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store); |
+ ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get()); |
// Set a lossy pref and check that it is not scheduled to be written. |
ASSERT_FALSE(file_writer->HasPendingWrite()); |
@@ -918,7 +917,7 @@ TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossyFirst) { |
TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossySecond) { |
scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore(); |
- ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store); |
+ ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get()); |
// Set a normal pref and check that it is scheduled to be written. |
ASSERT_FALSE(file_writer->HasPendingWrite()); |
@@ -940,7 +939,7 @@ TEST_F(JsonPrefStoreLossyWriteTest, LossyWriteMixedLossySecond) { |
TEST_F(JsonPrefStoreLossyWriteTest, ScheduleLossyWrite) { |
scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore(); |
- ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store); |
+ ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get()); |
// Set a lossy pref and check that it is not scheduled to be written. |
pref_store->SetValue("lossy", base::MakeUnique<base::StringValue>("lossy"), |
@@ -958,4 +957,205 @@ TEST_F(JsonPrefStoreLossyWriteTest, ScheduleLossyWrite) { |
ASSERT_EQ("{\"lossy\":\"lossy\"}", GetTestFileContents()); |
} |
-} // namespace base |
+class SuccessfulWriteReplyObserver { |
+ public: |
+ SuccessfulWriteReplyObserver() {} |
gab
2016/09/20 01:27:42
s/{}/= default;/
proberge
2016/09/20 15:15:53
Done.
|
+ |
+ // Returns true if a successful write was observed via on_successful_write() |
+ // and resets the observation state to false regardless. |
+ bool GetAndResetObservationState() { |
+ bool was_successful_write_observed = successful_write_reply_observed_; |
+ successful_write_reply_observed_ = false; |
+ return was_successful_write_observed; |
+ } |
+ |
+ // Register OnWrite() to be called on the next write of |json_pref_store|. |
+ void ObserveNextWriteCallback(JsonPrefStore* json_pref_store); |
+ |
+ void OnSuccessfulWrite() { |
+ EXPECT_FALSE(successful_write_reply_observed_); |
+ successful_write_reply_observed_ = true; |
+ } |
+ |
+ private: |
+ bool successful_write_reply_observed_ = false; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SuccessfulWriteReplyObserver); |
+}; |
+ |
+void SuccessfulWriteReplyObserver::ObserveNextWriteCallback( |
+ JsonPrefStore* json_pref_store) { |
+ json_pref_store->RegisterOnNextSuccessfulWriteReply( |
+ base::Bind(&SuccessfulWriteReplyObserver::OnSuccessfulWrite, |
+ base::Unretained(this))); |
+} |
+ |
+enum WriteCallbackObservationState { |
+ NOT_CALLED, |
+ CALLED_WITH_ERROR, |
+ CALLED_WITH_SUCCESS, |
+}; |
+ |
+class WriteCallbackObserver { |
+ public: |
+ WriteCallbackObserver() {} |
gab
2016/09/20 01:27:42
= default
proberge
2016/09/20 15:15:53
Done.
|
+ |
+ // Register OnWrite() to be called on the next write of |json_pref_store|. |
+ void ObserveNextWriteCallback(JsonPrefStore* json_pref_store); |
+ |
+ // Returns true if a write was observed via OnWrite() |
+ // and resets the observation state to false regardless. |
+ WriteCallbackObservationState GetAndResetObservationState(); |
+ |
+ void OnWrite(bool success) { |
+ EXPECT_EQ(NOT_CALLED, observation_state_); |
+ observation_state_ = success ? CALLED_WITH_SUCCESS : CALLED_WITH_ERROR; |
+ } |
+ |
+ private: |
+ WriteCallbackObservationState observation_state_ = NOT_CALLED; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WriteCallbackObserver); |
+}; |
+ |
+void WriteCallbackObserver::ObserveNextWriteCallback(JsonPrefStore* writer) { |
+ writer->RegisterOnNextWriteCallback( |
+ base::Bind(&WriteCallbackObserver::OnWrite, base::Unretained(this))); |
+} |
+ |
+WriteCallbackObservationState |
+WriteCallbackObserver::GetAndResetObservationState() { |
+ WriteCallbackObservationState state = observation_state_; |
+ observation_state_ = NOT_CALLED; |
+ return state; |
+} |
+ |
+class JsonPrefStoreCallbackTest : public JsonPrefStoreTest { |
+ protected: |
+ void SetUp() override { |
+ JsonPrefStoreTest::SetUp(); |
+ test_file_ = temp_dir_.path().AppendASCII("test.json"); |
+ } |
+ |
+ scoped_refptr<JsonPrefStore> CreatePrefStore() { |
+ return new JsonPrefStore(test_file_, message_loop_.task_runner(), |
+ std::unique_ptr<PrefFilter>()); |
+ } |
+ |
+ // Return the ImportantFileWriter for a given JsonPrefStore. |
+ ImportantFileWriter* GetImportantFileWriter(JsonPrefStore* pref_store) { |
+ return &(pref_store->writer_); |
+ } |
+ |
+ void TriggerFakeWriteForCallback(JsonPrefStore* pref_store, bool success) { |
+ JsonPrefStore::PostWriteCallback( |
+ pref_store->AsWeakPtr(), |
+ base::Bind(&WriteCallbackObserver::OnWrite, |
+ base::Unretained(&write_callback_observer_)), |
+ base::SequencedTaskRunnerHandle::Get(), success); |
+ } |
+ |
+ SuccessfulWriteReplyObserver successful_write_reply_observer_; |
+ WriteCallbackObserver write_callback_observer_; |
+ |
+ private: |
+ base::FilePath test_file_; |
+}; |
+ |
+TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallback) { |
+ scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore(); |
+ ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get()); |
+ |
+ // Test RegisterOnNextWriteCallback after RegisterOnNextSuccessfulWriteReply. |
+ successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get()); |
+ write_callback_observer_.ObserveNextWriteCallback(pref_store.get()); |
+ file_writer->WriteNow(MakeUnique<std::string>("foo")); |
+ RunLoop().RunUntilIdle(); |
+ EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState()); |
+ EXPECT_TRUE(write_callback_observer_.GetAndResetObservationState()); |
+ |
+ // Test RegisterOnNextSuccessfulWriteReply after RegisterOnNextWriteCallback. |
+ successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get()); |
+ write_callback_observer_.ObserveNextWriteCallback(pref_store.get()); |
+ file_writer->WriteNow(MakeUnique<std::string>("foo")); |
+ RunLoop().RunUntilIdle(); |
+ EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState()); |
+ EXPECT_TRUE(write_callback_observer_.GetAndResetObservationState()); |
+ |
+ // Test RegisterOnNextSuccessfulWriteReply only. |
+ successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get()); |
+ file_writer->WriteNow(MakeUnique<std::string>("foo")); |
+ RunLoop().RunUntilIdle(); |
+ EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState()); |
+ EXPECT_FALSE(write_callback_observer_.GetAndResetObservationState()); |
+ |
+ // Test RegisterOnNextWriteCallback only. |
+ write_callback_observer_.ObserveNextWriteCallback(pref_store.get()); |
+ file_writer->WriteNow(MakeUnique<std::string>("foo")); |
+ RunLoop().RunUntilIdle(); |
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState()); |
+ EXPECT_TRUE(write_callback_observer_.GetAndResetObservationState()); |
+} |
+ |
+TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbackWithFakeFailure) { |
+ scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore(); |
+ |
+ // Confirm that the observers are invoked. |
+ successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get()); |
+ TriggerFakeWriteForCallback(pref_store.get(), true); |
+ RunLoop().RunUntilIdle(); |
+ EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState()); |
+ EXPECT_EQ(CALLED_WITH_SUCCESS, |
+ write_callback_observer_.GetAndResetObservationState()); |
+ |
+ // Confirm that the observation states were reset. |
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState()); |
+ EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState()); |
+ |
+ // Confirm that re-installing the observers works for another write. |
+ successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get()); |
+ TriggerFakeWriteForCallback(pref_store.get(), true); |
+ RunLoop().RunUntilIdle(); |
+ EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState()); |
+ EXPECT_EQ(CALLED_WITH_SUCCESS, |
+ write_callback_observer_.GetAndResetObservationState()); |
+ |
+ // Confirm that the successful observer is not invoked by an unsuccessful |
+ // write, and that the synchronous observer is invoked. |
+ successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get()); |
+ TriggerFakeWriteForCallback(pref_store.get(), false); |
+ RunLoop().RunUntilIdle(); |
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState()); |
+ EXPECT_EQ(CALLED_WITH_ERROR, |
+ write_callback_observer_.GetAndResetObservationState()); |
+ |
+ // Do a real write, and confirm that the successful observer was invoked after |
+ // being set by |PostWriteCallback| by the last TriggerFakeWriteCallback. |
+ ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store.get()); |
+ file_writer->WriteNow(MakeUnique<std::string>("foo")); |
+ RunLoop().RunUntilIdle(); |
+ EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState()); |
+ EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState()); |
+} |
+ |
+TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallbackDuringProfileDeath) { |
+ // Create a JsonPrefStore and attach observers to it, then delete it by making |
+ // it go out of scope to simulate profile switch or Chrome shutdown. |
+ { |
+ scoped_refptr<JsonPrefStore> soon_out_of_scope_pref_store = |
+ CreatePrefStore(); |
+ ImportantFileWriter* file_writer = |
+ GetImportantFileWriter(soon_out_of_scope_pref_store.get()); |
+ successful_write_reply_observer_.ObserveNextWriteCallback( |
+ soon_out_of_scope_pref_store.get()); |
+ write_callback_observer_.ObserveNextWriteCallback( |
+ soon_out_of_scope_pref_store.get()); |
+ file_writer->WriteNow(MakeUnique<std::string>("foo")); |
+ } |
+ RunLoop().RunUntilIdle(); |
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState()); |
+ EXPECT_EQ(CALLED_WITH_SUCCESS, |
+ write_callback_observer_.GetAndResetObservationState()); |
+} |
+ |
+} // namespace base |