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

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: update some comments 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
« no previous file with comments | « base/files/important_file_writer.cc ('k') | chrome/browser/prefs/profile_pref_store_manager.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 successful_write_observed_ = true; 64 successful_write_observed_ = true;
65 } 65 }
66 66
67 bool successful_write_observed_; 67 bool successful_write_observed_;
68 68
69 DISALLOW_COPY_AND_ASSIGN(SuccessfulWriteObserver); 69 DISALLOW_COPY_AND_ASSIGN(SuccessfulWriteObserver);
70 }; 70 };
71 71
72 void SuccessfulWriteObserver::ObserveNextSuccessfulWrite( 72 void SuccessfulWriteObserver::ObserveNextSuccessfulWrite(
73 ImportantFileWriter* writer) { 73 ImportantFileWriter* writer) {
74 writer->RegisterOnNextSuccessfulWriteCallback(base::Bind( 74 writer->RegisterOnNextSuccessfulWriteReply(base::Bind(
75 &SuccessfulWriteObserver::on_successful_write, base::Unretained(this))); 75 &SuccessfulWriteObserver::on_successful_write, base::Unretained(this)));
76 } 76 }
77 77
78 bool SuccessfulWriteObserver::GetAndResetObservationState() { 78 bool SuccessfulWriteObserver::GetAndResetObservationState() {
79 bool was_successful_write_observed = successful_write_observed_; 79 bool was_successful_write_observed = successful_write_observed_;
80 successful_write_observed_ = false; 80 successful_write_observed_ = false;
81 return was_successful_write_observed; 81 return was_successful_write_observed;
82 } 82 }
83 83
84 enum WriteCallbackObservationState {
85 NOT_CALLED,
86 CALLED_WITH_ERROR,
87 CALLED_WITH_SUCCESS,
88 };
89
90 class SynchronousWriteCallbackObserver {
91 public:
92 SynchronousWriteCallbackObserver() : observation_state_(NOT_CALLED) {}
93
94 // Register on_write() to be called on the next write of |writer|.
95 void ObserveNextWriteCallback(ImportantFileWriter* writer);
96
97 // Returns true if a write was observed via on_write()
98 // and resets the observation state to false regardless.
99 WriteCallbackObservationState GetAndResetObservationState();
100
101 private:
102 void on_write(bool success) {
103 EXPECT_EQ(NOT_CALLED, observation_state_);
104 observation_state_ = success ? CALLED_WITH_SUCCESS : CALLED_WITH_ERROR;
105 }
106
107 WriteCallbackObservationState observation_state_;
108
109 DISALLOW_COPY_AND_ASSIGN(SynchronousWriteCallbackObserver);
110 };
111
112 void SynchronousWriteCallbackObserver::ObserveNextWriteCallback(
113 ImportantFileWriter* writer) {
114 writer->RegisterOnNextWriteSynchronousCallback(base::Bind(
115 &SynchronousWriteCallbackObserver::on_write, base::Unretained(this)));
116 }
117
118 WriteCallbackObservationState
119 SynchronousWriteCallbackObserver::GetAndResetObservationState() {
120 WriteCallbackObservationState state = observation_state_;
121 observation_state_ = NOT_CALLED;
122 return state;
123 }
124
84 } // namespace 125 } // namespace
85 126
86 class ImportantFileWriterTest : public testing::Test { 127 class ImportantFileWriterTest : public testing::Test {
87 public: 128 public:
88 ImportantFileWriterTest() { } 129 ImportantFileWriterTest()
130 : io_thread_("ImportantFileWriter test IO thread"),
131 wait_helper_(base::WaitableEvent::ResetPolicy::MANUAL,
132 base::WaitableEvent::InitialState::NOT_SIGNALED) {
133 io_thread_.StartWithOptions(
134 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
gab 2016/09/07 19:40:52 I don't think you specifically need an IO thread (
proberge 2016/09/08 17:19:31 Done.
135 }
136
137 ~ImportantFileWriterTest() { io_thread_.Stop(); }
gab 2016/09/07 19:40:52 Stop() is implicit in base::Thread's destructor, d
proberge 2016/09/08 17:19:31 Done.
138
89 void SetUp() override { 139 void SetUp() override {
90 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 140 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
91 file_ = temp_dir_.path().AppendASCII("test-file"); 141 file_ = temp_dir_.path().AppendASCII("test-file");
92 } 142 }
93 143
144 void WaitForWriteTask() {
145 wait_helper_.Reset();
146 io_thread_.task_runner()->PostTask(
147 FROM_HERE, base::Bind(&base::WaitableEvent::Signal,
148 base::Unretained(&wait_helper_)));
149 wait_helper_.Wait();
150 }
151
152 scoped_refptr<SingleThreadTaskRunner> GetTestThreadTaskRunner() {
153 return io_thread_.task_runner();
154 }
155
94 protected: 156 protected:
95 SuccessfulWriteObserver successful_write_observer_; 157 SuccessfulWriteObserver successful_write_reply_observer_;
158 SynchronousWriteCallbackObserver write_callback_observer_;
96 FilePath file_; 159 FilePath file_;
97 MessageLoop loop_; 160 MessageLoop loop_;
98 161
99 private: 162 private:
100 ScopedTempDir temp_dir_; 163 ScopedTempDir temp_dir_;
164
165 // Used for fine-grained control of thread execution.
166 base::Thread io_thread_;
167 base::WaitableEvent wait_helper_;
101 }; 168 };
102 169
103 TEST_F(ImportantFileWriterTest, Basic) { 170 TEST_F(ImportantFileWriterTest, Basic) {
104 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get()); 171 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
105 EXPECT_FALSE(PathExists(writer.path())); 172 EXPECT_FALSE(PathExists(writer.path()));
106 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 173 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
174 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
107 writer.WriteNow(WrapUnique(new std::string("foo"))); 175 writer.WriteNow(WrapUnique(new std::string("foo")));
108 RunLoop().RunUntilIdle(); 176 RunLoop().RunUntilIdle();
109 177
110 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 178 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
179 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
111 ASSERT_TRUE(PathExists(writer.path())); 180 ASSERT_TRUE(PathExists(writer.path()));
112 EXPECT_EQ("foo", GetFileContent(writer.path())); 181 EXPECT_EQ("foo", GetFileContent(writer.path()));
113 } 182 }
114 183
115 TEST_F(ImportantFileWriterTest, BasicWithSuccessfulWriteObserver) { 184 TEST_F(ImportantFileWriterTest, BasicWithWriteObservers) {
116 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get()); 185 ImportantFileWriter writer(file_, GetTestThreadTaskRunner());
gab 2016/09/07 19:40:52 Since it's only for this test actually, bring the
proberge 2016/09/08 17:19:31 Done. I thought it would be useful to have it in t
gab 2016/09/08 17:50:46 Right, except that it then started an unnecessary
186
117 EXPECT_FALSE(PathExists(writer.path())); 187 EXPECT_FALSE(PathExists(writer.path()));
118 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 188 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
119 successful_write_observer_.ObserveNextSuccessfulWrite(&writer); 189 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
190 successful_write_reply_observer_.ObserveNextSuccessfulWrite(&writer);
191 write_callback_observer_.ObserveNextWriteCallback(&writer);
192 writer.WriteNow(WrapUnique(new std::string("foo")));
193
194 // Make sure tasks posted by WriteNow() have ran before continuing.
195 WaitForWriteTask();
196
197 // The |successful_write_reply_observer_| should not yet have been
198 // notified yet but the |write_callback_observer_| should have been.
199 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
200 EXPECT_EQ(CALLED_WITH_SUCCESS,
201 write_callback_observer_.GetAndResetObservationState());
202
203 // There should be a pending task to notify |successful_write_reply_observer_|
204 // in this message loop.
205 RunLoop().RunUntilIdle();
206
207 // Confirm that the observer is invoked.
208 EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
209 ASSERT_TRUE(PathExists(writer.path()));
210 EXPECT_EQ("foo", GetFileContent(writer.path()));
211
212 // Confirm that re-installing the observers works for another write.
213 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
214 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
215 successful_write_reply_observer_.ObserveNextSuccessfulWrite(&writer);
216 write_callback_observer_.ObserveNextWriteCallback(&writer);
217 writer.WriteNow(WrapUnique(new std::string("bar")));
218
219 WaitForWriteTask();
220
221 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
222 EXPECT_EQ(CALLED_WITH_SUCCESS,
223 write_callback_observer_.GetAndResetObservationState());
224
225 RunLoop().RunUntilIdle();
226
227 EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
228 ASSERT_TRUE(PathExists(writer.path()));
229 EXPECT_EQ("bar", GetFileContent(writer.path()));
230
231 // Confirm that writing again without re-installing the observers doesn't
232 // result in a notification.
233 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
234 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
235 writer.WriteNow(WrapUnique(new std::string("baz")));
236
237 WaitForWriteTask();
238 RunLoop().RunUntilIdle();
239
240 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
241 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
242 ASSERT_TRUE(PathExists(writer.path()));
243 EXPECT_EQ("baz", GetFileContent(writer.path()));
244 }
245
246 TEST_F(ImportantFileWriterTest, FailedWriteWithWriteObservers) {
247 // Use an invalid file path (relative paths are invalid) to get a
248 // FILE_ERROR_ACCESS_DENIED error when trying to write the file.
249 ImportantFileWriter writer(FilePath().AppendASCII("bad/../path"),
250 ThreadTaskRunnerHandle::Get());
251 EXPECT_FALSE(PathExists(writer.path()));
252 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
253 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
254 successful_write_reply_observer_.ObserveNextSuccessfulWrite(&writer);
255 write_callback_observer_.ObserveNextWriteCallback(&writer);
120 writer.WriteNow(WrapUnique(new std::string("foo"))); 256 writer.WriteNow(WrapUnique(new std::string("foo")));
121 RunLoop().RunUntilIdle(); 257 RunLoop().RunUntilIdle();
122 258
123 // Confirm that the observer is invoked. 259 // Confirm that the successful write observer was not invoked, and that the
124 EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState()); 260 // write observer was invoked with its boolean parameter set to false.
125 ASSERT_TRUE(PathExists(writer.path())); 261 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
126 EXPECT_EQ("foo", GetFileContent(writer.path())); 262 EXPECT_EQ(CALLED_WITH_ERROR,
127 263 write_callback_observer_.GetAndResetObservationState());
128 // Confirm that re-installing the observer works for another write. 264 EXPECT_FALSE(PathExists(writer.path()));
129 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
130 successful_write_observer_.ObserveNextSuccessfulWrite(&writer);
131 writer.WriteNow(WrapUnique(new std::string("bar")));
132 RunLoop().RunUntilIdle();
133
134 EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState());
135 ASSERT_TRUE(PathExists(writer.path()));
136 EXPECT_EQ("bar", GetFileContent(writer.path()));
137
138 // Confirm that writing again without re-installing the observer doesn't
139 // result in a notification.
140 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
141 writer.WriteNow(WrapUnique(new std::string("baz")));
142 RunLoop().RunUntilIdle();
143
144 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
145 ASSERT_TRUE(PathExists(writer.path()));
146 EXPECT_EQ("baz", GetFileContent(writer.path()));
147 } 265 }
148 266
149 TEST_F(ImportantFileWriterTest, ScheduleWrite) { 267 TEST_F(ImportantFileWriterTest, ScheduleWrite) {
150 ImportantFileWriter writer(file_, 268 ImportantFileWriter writer(file_,
151 ThreadTaskRunnerHandle::Get(), 269 ThreadTaskRunnerHandle::Get(),
152 TimeDelta::FromMilliseconds(25)); 270 TimeDelta::FromMilliseconds(25));
153 EXPECT_FALSE(writer.HasPendingWrite()); 271 EXPECT_FALSE(writer.HasPendingWrite());
154 DataSerializer serializer("foo"); 272 DataSerializer serializer("foo");
155 writer.ScheduleWrite(&serializer); 273 writer.ScheduleWrite(&serializer);
156 EXPECT_TRUE(writer.HasPendingWrite()); 274 EXPECT_TRUE(writer.HasPendingWrite());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 writer.ScheduleWrite(&baz); 307 writer.ScheduleWrite(&baz);
190 ThreadTaskRunnerHandle::Get()->PostDelayedTask( 308 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
191 FROM_HERE, MessageLoop::QuitWhenIdleClosure(), 309 FROM_HERE, MessageLoop::QuitWhenIdleClosure(),
192 TimeDelta::FromMilliseconds(100)); 310 TimeDelta::FromMilliseconds(100));
193 RunLoop().Run(); 311 RunLoop().Run();
194 ASSERT_TRUE(PathExists(writer.path())); 312 ASSERT_TRUE(PathExists(writer.path()));
195 EXPECT_EQ("baz", GetFileContent(writer.path())); 313 EXPECT_EQ("baz", GetFileContent(writer.path()));
196 } 314 }
197 315
198 } // namespace base 316 } // namespace base
OLDNEW
« no previous file with comments | « base/files/important_file_writer.cc ('k') | chrome/browser/prefs/profile_pref_store_manager.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698