Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Unified Diff: base/files/important_file_writer_unittest.cc

Issue 2299523003: Add synchronous callback support to important_file_writer.cc (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Re-add accidentaly removed test fixture ctor Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/files/important_file_writer_unittest.cc
diff --git a/base/files/important_file_writer_unittest.cc b/base/files/important_file_writer_unittest.cc
index 6b5e32d85f43f6b8a2dfc5dc2d307baf99626690..605187218bdc6efec7e8047d650c7f89afd6e59c 100644
--- a/base/files/important_file_writer_unittest.cc
+++ b/base/files/important_file_writer_unittest.cc
@@ -71,7 +71,7 @@ class SuccessfulWriteObserver {
void SuccessfulWriteObserver::ObserveNextSuccessfulWrite(
ImportantFileWriter* writer) {
- writer->RegisterOnNextSuccessfulWriteCallback(base::Bind(
+ writer->RegisterOnNextSuccessfulWriteReply(base::Bind(
&SuccessfulWriteObserver::on_successful_write, base::Unretained(this)));
}
@@ -81,6 +81,47 @@ bool SuccessfulWriteObserver::GetAndResetObservationState() {
return was_successful_write_observed;
}
+enum WriteCallbackObservationState {
+ NOT_CALLED,
+ CALLED_WITH_ERROR,
+ CALLED_WITH_SUCCESS,
+};
+
+class SynchronousWriteCallbackObserver {
+ public:
+ SynchronousWriteCallbackObserver() : observation_state_(NOT_CALLED) {}
+
+ // Register on_write() to be called on the next write of |writer|.
+ void ObserveNextWriteCallback(ImportantFileWriter* writer);
+
+ // Returns true if a write was observed via on_write()
+ // and resets the observation state to false regardless.
+ WriteCallbackObservationState GetAndResetObservationState();
+
+ private:
+ void on_write(bool success) {
dcheng 2016/09/09 05:18:59 Nit: Chromium style dictates that this should be n
proberge 2016/09/09 17:24:00 Done.
gab 2016/09/09 19:35:37 I hadn't mentioned this mostly because the approac
proberge 2016/09/09 19:45:19 Done.
+ EXPECT_EQ(NOT_CALLED, observation_state_);
+ observation_state_ = success ? CALLED_WITH_SUCCESS : CALLED_WITH_ERROR;
+ }
+
+ WriteCallbackObservationState observation_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(SynchronousWriteCallbackObserver);
+};
+
+void SynchronousWriteCallbackObserver::ObserveNextWriteCallback(
+ ImportantFileWriter* writer) {
+ writer->RegisterOnNextWriteSynchronousCallback(base::Bind(
+ &SynchronousWriteCallbackObserver::on_write, base::Unretained(this)));
+}
+
+WriteCallbackObservationState
+SynchronousWriteCallbackObserver::GetAndResetObservationState() {
+ WriteCallbackObservationState state = observation_state_;
+ observation_state_ = NOT_CALLED;
+ return state;
+}
+
} // namespace
class ImportantFileWriterTest : public testing::Test {
@@ -92,7 +133,8 @@ class ImportantFileWriterTest : public testing::Test {
}
protected:
- SuccessfulWriteObserver successful_write_observer_;
+ SuccessfulWriteObserver successful_write_reply_observer_;
+ SynchronousWriteCallbackObserver write_callback_observer_;
FilePath file_;
MessageLoop loop_;
@@ -103,49 +145,118 @@ class ImportantFileWriterTest : public testing::Test {
TEST_F(ImportantFileWriterTest, Basic) {
ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
EXPECT_FALSE(PathExists(writer.path()));
- EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
+ EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
writer.WriteNow(WrapUnique(new std::string("foo")));
RunLoop().RunUntilIdle();
- EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
+ EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
ASSERT_TRUE(PathExists(writer.path()));
EXPECT_EQ("foo", GetFileContent(writer.path()));
}
-TEST_F(ImportantFileWriterTest, BasicWithSuccessfulWriteObserver) {
- ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
+TEST_F(ImportantFileWriterTest, BasicWithWriteObservers) {
+ base::Thread file_writer_thread("ImportantFileWriter test thread");
+ file_writer_thread.StartWithOptions(
gab 2016/09/08 17:50:46 Start() will do just that by default, use that ins
proberge 2016/09/08 20:08:34 Done.
+ base::Thread::Options(base::MessageLoop::TYPE_DEFAULT, 0));
+ base::WaitableEvent wait_helper(
+ base::WaitableEvent::ResetPolicy::MANUAL,
gab 2016/09/08 17:50:46 Make this AUTOMATIC, then you don't have to ever m
proberge 2016/09/08 20:08:34 Done.
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ ImportantFileWriter writer(file_, file_writer_thread.task_runner());
+
EXPECT_FALSE(PathExists(writer.path()));
- EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
- successful_write_observer_.ObserveNextSuccessfulWrite(&writer);
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
+ EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
+ successful_write_reply_observer_.ObserveNextSuccessfulWrite(&writer);
+ write_callback_observer_.ObserveNextWriteCallback(&writer);
writer.WriteNow(WrapUnique(new std::string("foo")));
+
+ // Make sure tasks posted by WriteNow() have ran before continuing.
+ wait_helper.Reset();
+ file_writer_thread.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&base::WaitableEvent::Signal, base::Unretained(&wait_helper)));
+ wait_helper.Wait();
+
+ // The |successful_write_reply_observer_| should not yet have been
+ // notified yet but the |write_callback_observer_| should have been.
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
+ EXPECT_EQ(CALLED_WITH_SUCCESS,
+ write_callback_observer_.GetAndResetObservationState());
+
+ // There should be a pending task to notify |successful_write_reply_observer_|
+ // in this message loop.
RunLoop().RunUntilIdle();
// Confirm that the observer is invoked.
- EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState());
+ EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
ASSERT_TRUE(PathExists(writer.path()));
EXPECT_EQ("foo", GetFileContent(writer.path()));
- // Confirm that re-installing the observer works for another write.
- EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
- successful_write_observer_.ObserveNextSuccessfulWrite(&writer);
+ // Confirm that re-installing the observers works for another write.
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
+ EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
+ successful_write_reply_observer_.ObserveNextSuccessfulWrite(&writer);
+ write_callback_observer_.ObserveNextWriteCallback(&writer);
writer.WriteNow(WrapUnique(new std::string("bar")));
+
+ wait_helper.Reset();
+ file_writer_thread.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&base::WaitableEvent::Signal, base::Unretained(&wait_helper)));
+ wait_helper.Wait();
+
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
+ EXPECT_EQ(CALLED_WITH_SUCCESS,
+ write_callback_observer_.GetAndResetObservationState());
+
RunLoop().RunUntilIdle();
- EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState());
+ EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
ASSERT_TRUE(PathExists(writer.path()));
EXPECT_EQ("bar", GetFileContent(writer.path()));
- // Confirm that writing again without re-installing the observer doesn't
+ // Confirm that writing again without re-installing the observers doesn't
// result in a notification.
- EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
+ EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
writer.WriteNow(WrapUnique(new std::string("baz")));
+
+ wait_helper.Reset();
+ file_writer_thread.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&base::WaitableEvent::Signal, base::Unretained(&wait_helper)));
+ wait_helper.Wait();
RunLoop().RunUntilIdle();
- EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
+ EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
ASSERT_TRUE(PathExists(writer.path()));
EXPECT_EQ("baz", GetFileContent(writer.path()));
}
+TEST_F(ImportantFileWriterTest, FailedWriteWithWriteObservers) {
+ // Use an invalid file path (relative paths are invalid) to get a
+ // FILE_ERROR_ACCESS_DENIED error when trying to write the file.
+ ImportantFileWriter writer(FilePath().AppendASCII("bad/../path"),
+ ThreadTaskRunnerHandle::Get());
+ EXPECT_FALSE(PathExists(writer.path()));
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
+ EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
+ successful_write_reply_observer_.ObserveNextSuccessfulWrite(&writer);
+ write_callback_observer_.ObserveNextWriteCallback(&writer);
+ writer.WriteNow(WrapUnique(new std::string("foo")));
+ RunLoop().RunUntilIdle();
+
+ // Confirm that the successful write observer was not invoked, and that the
+ // write observer was invoked with its boolean parameter set to false.
+ EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
+ EXPECT_EQ(CALLED_WITH_ERROR,
+ write_callback_observer_.GetAndResetObservationState());
+ EXPECT_FALSE(PathExists(writer.path()));
+}
+
TEST_F(ImportantFileWriterTest, ScheduleWrite) {
ImportantFileWriter writer(file_,
ThreadTaskRunnerHandle::Get(),

Powered by Google App Engine
This is Rietveld 408576698