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

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: 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 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 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) {
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.
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() { }
89 void SetUp() override { 130 void SetUp() override {
90 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 131 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
91 file_ = temp_dir_.GetPath().AppendASCII("test-file"); 132 file_ = temp_dir_.GetPath().AppendASCII("test-file");
92 } 133 }
93 134
94 protected: 135 protected:
95 SuccessfulWriteObserver successful_write_observer_; 136 SuccessfulWriteObserver successful_write_reply_observer_;
137 SynchronousWriteCallbackObserver write_callback_observer_;
96 FilePath file_; 138 FilePath file_;
97 MessageLoop loop_; 139 MessageLoop loop_;
98 140
99 private: 141 private:
100 ScopedTempDir temp_dir_; 142 ScopedTempDir temp_dir_;
101 }; 143 };
102 144
103 TEST_F(ImportantFileWriterTest, Basic) { 145 TEST_F(ImportantFileWriterTest, Basic) {
104 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get()); 146 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
105 EXPECT_FALSE(PathExists(writer.path())); 147 EXPECT_FALSE(PathExists(writer.path()));
106 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 148 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
149 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
107 writer.WriteNow(WrapUnique(new std::string("foo"))); 150 writer.WriteNow(WrapUnique(new std::string("foo")));
108 RunLoop().RunUntilIdle(); 151 RunLoop().RunUntilIdle();
109 152
110 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 153 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
154 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
111 ASSERT_TRUE(PathExists(writer.path())); 155 ASSERT_TRUE(PathExists(writer.path()));
112 EXPECT_EQ("foo", GetFileContent(writer.path())); 156 EXPECT_EQ("foo", GetFileContent(writer.path()));
113 } 157 }
114 158
115 TEST_F(ImportantFileWriterTest, BasicWithSuccessfulWriteObserver) { 159 TEST_F(ImportantFileWriterTest, BasicWithWriteObservers) {
116 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get()); 160 base::Thread file_writer_thread("ImportantFileWriter test thread");
161 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.
162 base::Thread::Options(base::MessageLoop::TYPE_DEFAULT, 0));
163 base::WaitableEvent wait_helper(
164 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.
165 base::WaitableEvent::InitialState::NOT_SIGNALED);
166 ImportantFileWriter writer(file_, file_writer_thread.task_runner());
167
117 EXPECT_FALSE(PathExists(writer.path())); 168 EXPECT_FALSE(PathExists(writer.path()));
118 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 169 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
119 successful_write_observer_.ObserveNextSuccessfulWrite(&writer); 170 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
171 successful_write_reply_observer_.ObserveNextSuccessfulWrite(&writer);
172 write_callback_observer_.ObserveNextWriteCallback(&writer);
173 writer.WriteNow(WrapUnique(new std::string("foo")));
174
175 // Make sure tasks posted by WriteNow() have ran before continuing.
176 wait_helper.Reset();
177 file_writer_thread.task_runner()->PostTask(
178 FROM_HERE,
179 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&wait_helper)));
180 wait_helper.Wait();
181
182 // The |successful_write_reply_observer_| should not yet have been
183 // notified yet but the |write_callback_observer_| should have been.
184 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
185 EXPECT_EQ(CALLED_WITH_SUCCESS,
186 write_callback_observer_.GetAndResetObservationState());
187
188 // There should be a pending task to notify |successful_write_reply_observer_|
189 // in this message loop.
190 RunLoop().RunUntilIdle();
191
192 // Confirm that the observer is invoked.
193 EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
194 ASSERT_TRUE(PathExists(writer.path()));
195 EXPECT_EQ("foo", GetFileContent(writer.path()));
196
197 // Confirm that re-installing the observers works for another write.
198 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
199 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
200 successful_write_reply_observer_.ObserveNextSuccessfulWrite(&writer);
201 write_callback_observer_.ObserveNextWriteCallback(&writer);
202 writer.WriteNow(WrapUnique(new std::string("bar")));
203
204 wait_helper.Reset();
205 file_writer_thread.task_runner()->PostTask(
206 FROM_HERE,
207 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&wait_helper)));
208 wait_helper.Wait();
209
210 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
211 EXPECT_EQ(CALLED_WITH_SUCCESS,
212 write_callback_observer_.GetAndResetObservationState());
213
214 RunLoop().RunUntilIdle();
215
216 EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
217 ASSERT_TRUE(PathExists(writer.path()));
218 EXPECT_EQ("bar", GetFileContent(writer.path()));
219
220 // Confirm that writing again without re-installing the observers doesn't
221 // result in a notification.
222 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
223 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
224 writer.WriteNow(WrapUnique(new std::string("baz")));
225
226 wait_helper.Reset();
227 file_writer_thread.task_runner()->PostTask(
228 FROM_HERE,
229 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&wait_helper)));
230 wait_helper.Wait();
231 RunLoop().RunUntilIdle();
232
233 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
234 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
235 ASSERT_TRUE(PathExists(writer.path()));
236 EXPECT_EQ("baz", GetFileContent(writer.path()));
237 }
238
239 TEST_F(ImportantFileWriterTest, FailedWriteWithWriteObservers) {
240 // Use an invalid file path (relative paths are invalid) to get a
241 // FILE_ERROR_ACCESS_DENIED error when trying to write the file.
242 ImportantFileWriter writer(FilePath().AppendASCII("bad/../path"),
243 ThreadTaskRunnerHandle::Get());
244 EXPECT_FALSE(PathExists(writer.path()));
245 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
246 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
247 successful_write_reply_observer_.ObserveNextSuccessfulWrite(&writer);
248 write_callback_observer_.ObserveNextWriteCallback(&writer);
120 writer.WriteNow(WrapUnique(new std::string("foo"))); 249 writer.WriteNow(WrapUnique(new std::string("foo")));
121 RunLoop().RunUntilIdle(); 250 RunLoop().RunUntilIdle();
122 251
123 // Confirm that the observer is invoked. 252 // Confirm that the successful write observer was not invoked, and that the
124 EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState()); 253 // write observer was invoked with its boolean parameter set to false.
125 ASSERT_TRUE(PathExists(writer.path())); 254 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
126 EXPECT_EQ("foo", GetFileContent(writer.path())); 255 EXPECT_EQ(CALLED_WITH_ERROR,
127 256 write_callback_observer_.GetAndResetObservationState());
128 // Confirm that re-installing the observer works for another write. 257 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 } 258 }
148 259
149 TEST_F(ImportantFileWriterTest, ScheduleWrite) { 260 TEST_F(ImportantFileWriterTest, ScheduleWrite) {
150 ImportantFileWriter writer(file_, 261 ImportantFileWriter writer(file_,
151 ThreadTaskRunnerHandle::Get(), 262 ThreadTaskRunnerHandle::Get(),
152 TimeDelta::FromMilliseconds(25)); 263 TimeDelta::FromMilliseconds(25));
153 EXPECT_FALSE(writer.HasPendingWrite()); 264 EXPECT_FALSE(writer.HasPendingWrite());
154 DataSerializer serializer("foo"); 265 DataSerializer serializer("foo");
155 writer.ScheduleWrite(&serializer); 266 writer.ScheduleWrite(&serializer);
156 EXPECT_TRUE(writer.HasPendingWrite()); 267 EXPECT_TRUE(writer.HasPendingWrite());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 writer.ScheduleWrite(&baz); 300 writer.ScheduleWrite(&baz);
190 ThreadTaskRunnerHandle::Get()->PostDelayedTask( 301 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
191 FROM_HERE, MessageLoop::QuitWhenIdleClosure(), 302 FROM_HERE, MessageLoop::QuitWhenIdleClosure(),
192 TimeDelta::FromMilliseconds(100)); 303 TimeDelta::FromMilliseconds(100));
193 RunLoop().Run(); 304 RunLoop().Run();
194 ASSERT_TRUE(PathExists(writer.path())); 305 ASSERT_TRUE(PathExists(writer.path()));
195 EXPECT_EQ("baz", GetFileContent(writer.path())); 306 EXPECT_EQ("baz", GetFileContent(writer.path()));
196 } 307 }
197 308
198 } // namespace base 309 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698