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..f5fe991766614f704152b5f41e505af9b94a8eba 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" |
@@ -958,4 +959,215 @@ TEST_F(JsonPrefStoreLossyWriteTest, ScheduleLossyWrite) { |
ASSERT_EQ("{\"lossy\":\"lossy\"}", GetTestFileContents()); |
} |
-} // namespace base |
+class SuccessfulWriteReplyObserver { |
+ public: |
+ SuccessfulWriteReplyObserver() : successful_write_reply_observed_(false) {} |
+ |
+ // 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_; |
gab
2016/09/19 18:01:30
Use C++11 member initialization (i.e. = false here
proberge
2016/09/19 21:24:26
Done.
|
+ |
+ 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() : observation_state_(NOT_CALLED) {} |
+ |
+ // 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_; |
gab
2016/09/19 18:01:31
C++11 member init here too
proberge
2016/09/19 21:24:25
Done.
|
+ |
+ 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"); |
+ } |
+ |
+ // Creates a JsonPrefStore with the given |file_writer|. |
gab
2016/09/19 18:01:31
|file_writer| refers to nothing?
proberge
2016/09/19 21:24:26
Copied the comment from line 827. Removed the comm
|
+ scoped_refptr<JsonPrefStore> CreatePrefStore() { |
+ return new JsonPrefStore(test_file_, message_loop_.task_runner(), |
+ std::unique_ptr<PrefFilter>()); |
+ } |
+ |
+ // As above, but with a custom SequencedTaskRunner. |
+ scoped_refptr<JsonPrefStore> CreatePrefStore( |
+ scoped_refptr<SequencedTaskRunner> task_runner) { |
gab
2016/09/19 18:01:30
Unused? Should there be a test with an independent
proberge
2016/09/19 21:24:26
I thought I needed it for TestPostWriteCallbackDur
gab
2016/09/20 01:27:41
I guess it wouldn't do much more than re-test Impo
|
+ return new JsonPrefStore(test_file_, task_runner, |
+ std::unique_ptr<PrefFilter>()); |
+ } |
+ |
+ // Return the ImportantFileWriter for a given JsonPrefStore. |
+ ImportantFileWriter* GetImportantFileWriter( |
+ scoped_refptr<JsonPrefStore> pref_store) { |
gab
2016/09/19 18:01:30
scoped_refptr<JsonPrefStore> as a parameter implic
proberge
2016/09/19 21:24:26
Was copied from line 834. Updated there as well.
|
+ return &(pref_store->writer_); |
+ } |
+ |
+ void TriggerFakeWriteForCallback(scoped_refptr<JsonPrefStore> pref_store, |
gab
2016/09/19 18:01:30
Same here
proberge
2016/09/19 21:24:25
Done.
|
+ 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_; |
+}; |
gab
2016/09/19 18:01:30
DISALLOW_COPY_AND_ASSIGN
proberge
2016/09/19 21:24:26
Looks like DISALLOW_COPY_AND_ASSIGN isn't happy wi
dcheng
2016/09/20 01:08:57
You'll have to give the test an explicit default c
gab
2016/09/20 01:27:41
This is because DISALLOW_COPY_AND_ASSIGN is implem
proberge
2016/09/20 15:15:52
Done.
|
+ |
+TEST_F(JsonPrefStoreCallbackTest, TestPostWriteCallback) { |
+ scoped_refptr<JsonPrefStore> pref_store = CreatePrefStore(); |
+ ImportantFileWriter* file_writer = GetImportantFileWriter(pref_store); |
+ |
+ // Test RegisterOnNextWriteCallback after RegisterOnNextSuccessfulWriteReply. |
+ successful_write_reply_observer_.ObserveNextWriteCallback(pref_store.get()); |
+ write_callback_observer_.ObserveNextWriteCallback(pref_store.get()); |
+ file_writer->WriteNow(WrapUnique(new 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(WrapUnique(new 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(WrapUnique(new 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(WrapUnique(new 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, 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, 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, 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); |
+ file_writer->WriteNow(WrapUnique(new 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); |
+ 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(WrapUnique(new std::string("foo"))); |
+ } |
+ RunLoop().RunUntilIdle(); |
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState()); |
+ EXPECT_EQ(CALLED_WITH_SUCCESS, |
+ write_callback_observer_.GetAndResetObservationState()); |
+} |
+ |
+} // namespace base |