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

Side by Side 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: Address comments on #13 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/files/important_file_writer.h" 5 #include "base/files/important_file_writer.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
(...skipping 28 matching lines...) Expand all
39 39
40 bool SerializeData(std::string* output) override { 40 bool SerializeData(std::string* output) override {
41 output->assign(data_); 41 output->assign(data_);
42 return true; 42 return true;
43 } 43 }
44 44
45 private: 45 private:
46 const std::string data_; 46 const std::string data_;
47 }; 47 };
48 48
49 class SuccessfulWriteObserver { 49 enum WriteCallbackObservationState {
50 NOT_CALLED,
51 CALLED_WITH_ERROR,
52 CALLED_WITH_SUCCESS,
53 };
54
55 class WriteCallbackObserver {
50 public: 56 public:
51 SuccessfulWriteObserver() : successful_write_observed_(false) {} 57 WriteCallbackObserver() : observation_state_(NOT_CALLED) {}
52 58
53 // Register on_successful_write() to be called on the next successful write 59 // Register OnWrite() to be called on the next write of |writer|.
54 // of |writer|. 60 void ObserveNextWriteCallback(ImportantFileWriter* writer);
55 void ObserveNextSuccessfulWrite(ImportantFileWriter* writer);
56 61
57 // Returns true if a successful write was observed via on_successful_write() 62 // Returns true if a write was observed via OnWrite()
58 // and resets the observation state to false regardless. 63 // and resets the observation state to false regardless.
59 bool GetAndResetObservationState(); 64 WriteCallbackObservationState GetAndResetObservationState();
60 65
61 private: 66 private:
62 void on_successful_write() { 67 void OnWrite(bool success) {
63 EXPECT_FALSE(successful_write_observed_); 68 EXPECT_EQ(NOT_CALLED, observation_state_);
64 successful_write_observed_ = true; 69 observation_state_ = success ? CALLED_WITH_SUCCESS : CALLED_WITH_ERROR;
65 } 70 }
66 71
67 bool successful_write_observed_; 72 WriteCallbackObservationState observation_state_;
68 73
69 DISALLOW_COPY_AND_ASSIGN(SuccessfulWriteObserver); 74 DISALLOW_COPY_AND_ASSIGN(WriteCallbackObserver);
70 }; 75 };
71 76
72 void SuccessfulWriteObserver::ObserveNextSuccessfulWrite( 77 void WriteCallbackObserver::ObserveNextWriteCallback(
73 ImportantFileWriter* writer) { 78 ImportantFileWriter* writer) {
74 writer->RegisterOnNextSuccessfulWriteCallback(base::Bind( 79 writer->RegisterOnNextWriteCallback(
75 &SuccessfulWriteObserver::on_successful_write, base::Unretained(this))); 80 base::Bind(&WriteCallbackObserver::OnWrite, base::Unretained(this)));
76 } 81 }
77 82
78 bool SuccessfulWriteObserver::GetAndResetObservationState() { 83 WriteCallbackObservationState
79 bool was_successful_write_observed = successful_write_observed_; 84 WriteCallbackObserver::GetAndResetObservationState() {
80 successful_write_observed_ = false; 85 WriteCallbackObservationState state = observation_state_;
81 return was_successful_write_observed; 86 observation_state_ = NOT_CALLED;
87 return state;
82 } 88 }
83 89
84 } // namespace 90 } // namespace
85 91
86 class ImportantFileWriterTest : public testing::Test { 92 class ImportantFileWriterTest : public testing::Test {
87 public: 93 public:
88 ImportantFileWriterTest() { } 94 ImportantFileWriterTest() { }
89 void SetUp() override { 95 void SetUp() override {
90 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 96 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
91 file_ = temp_dir_.GetPath().AppendASCII("test-file"); 97 file_ = temp_dir_.GetPath().AppendASCII("test-file");
92 } 98 }
93 99
94 protected: 100 protected:
95 SuccessfulWriteObserver successful_write_observer_; 101 WriteCallbackObserver write_callback_observer_;
96 FilePath file_; 102 FilePath file_;
97 MessageLoop loop_; 103 MessageLoop loop_;
98 104
99 private: 105 private:
100 ScopedTempDir temp_dir_; 106 ScopedTempDir temp_dir_;
101 }; 107 };
102 108
103 TEST_F(ImportantFileWriterTest, Basic) { 109 TEST_F(ImportantFileWriterTest, Basic) {
104 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get()); 110 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
105 EXPECT_FALSE(PathExists(writer.path())); 111 EXPECT_FALSE(PathExists(writer.path()));
106 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 112 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
107 writer.WriteNow(MakeUnique<std::string>("foo")); 113 writer.WriteNow(MakeUnique<std::string>("foo"));
108 RunLoop().RunUntilIdle(); 114 RunLoop().RunUntilIdle();
109 115
110 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 116 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
111 ASSERT_TRUE(PathExists(writer.path())); 117 ASSERT_TRUE(PathExists(writer.path()));
112 EXPECT_EQ("foo", GetFileContent(writer.path())); 118 EXPECT_EQ("foo", GetFileContent(writer.path()));
113 } 119 }
114 120
115 TEST_F(ImportantFileWriterTest, BasicWithSuccessfulWriteObserver) { 121 TEST_F(ImportantFileWriterTest, WriteWithObserver) {
116 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get()); 122 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
117 EXPECT_FALSE(PathExists(writer.path())); 123 EXPECT_FALSE(PathExists(writer.path()));
118 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 124 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
119 successful_write_observer_.ObserveNextSuccessfulWrite(&writer); 125
126 // Confirm that the observer is invoked.
127 write_callback_observer_.ObserveNextWriteCallback(&writer);
120 writer.WriteNow(MakeUnique<std::string>("foo")); 128 writer.WriteNow(MakeUnique<std::string>("foo"));
121 RunLoop().RunUntilIdle(); 129 RunLoop().RunUntilIdle();
122 130
123 // Confirm that the observer is invoked. 131 EXPECT_EQ(CALLED_WITH_SUCCESS,
124 EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState()); 132 write_callback_observer_.GetAndResetObservationState());
125 ASSERT_TRUE(PathExists(writer.path())); 133 ASSERT_TRUE(PathExists(writer.path()));
126 EXPECT_EQ("foo", GetFileContent(writer.path())); 134 EXPECT_EQ("foo", GetFileContent(writer.path()));
127 135
128 // Confirm that re-installing the observer works for another write. 136 // Confirm that re-installing the observer works for another write.
129 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 137 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
130 successful_write_observer_.ObserveNextSuccessfulWrite(&writer); 138 write_callback_observer_.ObserveNextWriteCallback(&writer);
131 writer.WriteNow(MakeUnique<std::string>("bar")); 139 writer.WriteNow(MakeUnique<std::string>("bar"));
132 RunLoop().RunUntilIdle(); 140 RunLoop().RunUntilIdle();
133 141
134 EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState()); 142 EXPECT_EQ(CALLED_WITH_SUCCESS,
143 write_callback_observer_.GetAndResetObservationState());
135 ASSERT_TRUE(PathExists(writer.path())); 144 ASSERT_TRUE(PathExists(writer.path()));
136 EXPECT_EQ("bar", GetFileContent(writer.path())); 145 EXPECT_EQ("bar", GetFileContent(writer.path()));
137 146
138 // Confirm that writing again without re-installing the observer doesn't 147 // Confirm that writing again without re-installing the observer doesn't
139 // result in a notification. 148 // result in a notification.
140 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 149 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
141 writer.WriteNow(MakeUnique<std::string>("baz")); 150 writer.WriteNow(MakeUnique<std::string>("baz"));
142 RunLoop().RunUntilIdle(); 151 RunLoop().RunUntilIdle();
143 152
144 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 153 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
145 ASSERT_TRUE(PathExists(writer.path())); 154 ASSERT_TRUE(PathExists(writer.path()));
146 EXPECT_EQ("baz", GetFileContent(writer.path())); 155 EXPECT_EQ("baz", GetFileContent(writer.path()));
147 } 156 }
148 157
158 TEST_F(ImportantFileWriterTest, FailedWriteWithObserver) {
159 // Use an invalid file path (relative paths are invalid) to get a
160 // FILE_ERROR_ACCESS_DENIED error when trying to write the file.
161 ImportantFileWriter writer(FilePath().AppendASCII("bad/../path"),
162 ThreadTaskRunnerHandle::Get());
163 EXPECT_FALSE(PathExists(writer.path()));
164 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
165 write_callback_observer_.ObserveNextWriteCallback(&writer);
166 writer.WriteNow(MakeUnique<std::string>("foo"));
167 RunLoop().RunUntilIdle();
168
169 // Confirm that the write observer was invoked with its boolean parameter set
170 // to false.
171 EXPECT_EQ(CALLED_WITH_ERROR,
172 write_callback_observer_.GetAndResetObservationState());
173 EXPECT_FALSE(PathExists(writer.path()));
174 }
175
176 TEST_F(ImportantFileWriterTest, CallbackRunsOnWriterThread) {
177 base::Thread file_writer_thread("ImportantFileWriter test thread");
178 file_writer_thread.Start();
179 ImportantFileWriter writer(file_, file_writer_thread.task_runner());
180 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
181
182 write_callback_observer_.ObserveNextWriteCallback(&writer);
183 writer.WriteNow(MakeUnique<std::string>("foo"));
184 RunLoop().RunUntilIdle();
185
186 // Expect the callback to not have been executed before the write.
187 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
gab 2016/09/20 01:27:41 This is racy and you will need a WaitableEvent::Wa
proberge 2016/09/20 15:15:52 I don't see it: WriteNow posts a task on the file_
188
189 // Make sure tasks posted by WriteNow() have ran before continuing.
190 file_writer_thread.FlushForTesting();
191 EXPECT_EQ(CALLED_WITH_SUCCESS,
192 write_callback_observer_.GetAndResetObservationState());
193 ASSERT_TRUE(PathExists(writer.path()));
194 EXPECT_EQ("foo", GetFileContent(writer.path()));
195 }
196
149 TEST_F(ImportantFileWriterTest, ScheduleWrite) { 197 TEST_F(ImportantFileWriterTest, ScheduleWrite) {
150 ImportantFileWriter writer(file_, 198 ImportantFileWriter writer(file_,
151 ThreadTaskRunnerHandle::Get(), 199 ThreadTaskRunnerHandle::Get(),
152 TimeDelta::FromMilliseconds(25)); 200 TimeDelta::FromMilliseconds(25));
153 EXPECT_FALSE(writer.HasPendingWrite()); 201 EXPECT_FALSE(writer.HasPendingWrite());
154 DataSerializer serializer("foo"); 202 DataSerializer serializer("foo");
155 writer.ScheduleWrite(&serializer); 203 writer.ScheduleWrite(&serializer);
156 EXPECT_TRUE(writer.HasPendingWrite()); 204 EXPECT_TRUE(writer.HasPendingWrite());
157 ThreadTaskRunnerHandle::Get()->PostDelayedTask( 205 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
158 FROM_HERE, MessageLoop::QuitWhenIdleClosure(), 206 FROM_HERE, MessageLoop::QuitWhenIdleClosure(),
(...skipping 30 matching lines...) Expand all
189 writer.ScheduleWrite(&baz); 237 writer.ScheduleWrite(&baz);
190 ThreadTaskRunnerHandle::Get()->PostDelayedTask( 238 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
191 FROM_HERE, MessageLoop::QuitWhenIdleClosure(), 239 FROM_HERE, MessageLoop::QuitWhenIdleClosure(),
192 TimeDelta::FromMilliseconds(100)); 240 TimeDelta::FromMilliseconds(100));
193 RunLoop().Run(); 241 RunLoop().Run();
194 ASSERT_TRUE(PathExists(writer.path())); 242 ASSERT_TRUE(PathExists(writer.path()));
195 EXPECT_EQ("baz", GetFileContent(writer.path())); 243 EXPECT_EQ("baz", GetFileContent(writer.path()));
196 } 244 }
197 245
198 } // namespace base 246 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698