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

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: on_successful_write -> OnNextSuccessfulWrite for consistency 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 class SuccessfulWriteObserver {
50 public: 50 public:
51 SuccessfulWriteObserver() : successful_write_observed_(false) {} 51 SuccessfulWriteObserver() : successful_write_observed_(false) {}
52 52
53 // Register on_successful_write() to be called on the next successful write 53 // Register OnSuccessfulWrite() to be called on the next successful write
54 // of |writer|. 54 // of |writer|.
55 void ObserveNextSuccessfulWrite(ImportantFileWriter* writer); 55 void ObserveNextSuccessfulWrite(ImportantFileWriter* writer);
56 56
57 // Returns true if a successful write was observed via on_successful_write() 57 // Returns true if a successful write was observed via OnSuccessfulWrite()
58 // and resets the observation state to false regardless. 58 // and resets the observation state to false regardless.
59 bool GetAndResetObservationState(); 59 bool GetAndResetObservationState();
60 60
61 private: 61 private:
62 void on_successful_write() { 62 void OnSuccessfulWrite() {
63 EXPECT_FALSE(successful_write_observed_); 63 EXPECT_FALSE(successful_write_observed_);
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::OnSuccessfulWrite, 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 OnWrite() to be called on the next write of |writer|.
95 void ObserveNextWriteCallback(ImportantFileWriter* writer);
96
97 // Returns true if a write was observed via OnWrite()
98 // and resets the observation state to false regardless.
99 WriteCallbackObservationState GetAndResetObservationState();
100
101 private:
102 void OnWrite(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::OnWrite, 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.Start();
162 base::WaitableEvent wait_helper(
163 base::WaitableEvent::ResetPolicy::AUTOMATIC,
164 base::WaitableEvent::InitialState::NOT_SIGNALED);
165 ImportantFileWriter writer(file_, file_writer_thread.task_runner());
166
117 EXPECT_FALSE(PathExists(writer.path())); 167 EXPECT_FALSE(PathExists(writer.path()));
118 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 168 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
119 successful_write_observer_.ObserveNextSuccessfulWrite(&writer); 169 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
170 successful_write_reply_observer_.ObserveNextSuccessfulWrite(&writer);
171 write_callback_observer_.ObserveNextWriteCallback(&writer);
172 writer.WriteNow(WrapUnique(new std::string("foo")));
173
174 // Make sure tasks posted by WriteNow() have ran before continuing.
175 file_writer_thread.task_runner()->PostTask(
176 FROM_HERE,
177 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&wait_helper)));
178 wait_helper.Wait();
gab 2016/09/13 20:47:37 Note: I just grew tired of having to do and sugges
proberge 2016/09/14 14:33:33 Done. Thanks!
179
180 // The |successful_write_reply_observer_| should not yet have been
181 // notified yet but the |write_callback_observer_| should have been.
182 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
183 EXPECT_EQ(CALLED_WITH_SUCCESS,
184 write_callback_observer_.GetAndResetObservationState());
185
186 // There should be a pending task to notify |successful_write_reply_observer_|
187 // in this message loop.
188 RunLoop().RunUntilIdle();
189
190 // Confirm that the observer is invoked.
191 EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
192 ASSERT_TRUE(PathExists(writer.path()));
193 EXPECT_EQ("foo", GetFileContent(writer.path()));
194
195 // Confirm that re-installing the observers works for another write.
196 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
197 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
198 successful_write_reply_observer_.ObserveNextSuccessfulWrite(&writer);
199 write_callback_observer_.ObserveNextWriteCallback(&writer);
200 writer.WriteNow(WrapUnique(new std::string("bar")));
201
202 file_writer_thread.task_runner()->PostTask(
203 FROM_HERE,
204 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&wait_helper)));
205 wait_helper.Wait();
206
207 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
208 EXPECT_EQ(CALLED_WITH_SUCCESS,
209 write_callback_observer_.GetAndResetObservationState());
210
211 RunLoop().RunUntilIdle();
212
213 EXPECT_TRUE(successful_write_reply_observer_.GetAndResetObservationState());
214 ASSERT_TRUE(PathExists(writer.path()));
215 EXPECT_EQ("bar", GetFileContent(writer.path()));
216
217 // Confirm that writing again without re-installing the observers doesn't
218 // result in a notification.
219 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
220 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
221 writer.WriteNow(WrapUnique(new std::string("baz")));
222
223 file_writer_thread.task_runner()->PostTask(
224 FROM_HERE,
225 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&wait_helper)));
226 wait_helper.Wait();
227 RunLoop().RunUntilIdle();
228
229 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
230 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
231 ASSERT_TRUE(PathExists(writer.path()));
232 EXPECT_EQ("baz", GetFileContent(writer.path()));
233 }
234
235 TEST_F(ImportantFileWriterTest, FailedWriteWithWriteObservers) {
236 // Use an invalid file path (relative paths are invalid) to get a
237 // FILE_ERROR_ACCESS_DENIED error when trying to write the file.
238 ImportantFileWriter writer(FilePath().AppendASCII("bad/../path"),
239 ThreadTaskRunnerHandle::Get());
240 EXPECT_FALSE(PathExists(writer.path()));
241 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
242 EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
243 successful_write_reply_observer_.ObserveNextSuccessfulWrite(&writer);
244 write_callback_observer_.ObserveNextWriteCallback(&writer);
120 writer.WriteNow(WrapUnique(new std::string("foo"))); 245 writer.WriteNow(WrapUnique(new std::string("foo")));
121 RunLoop().RunUntilIdle(); 246 RunLoop().RunUntilIdle();
122 247
123 // Confirm that the observer is invoked. 248 // Confirm that the successful write observer was not invoked, and that the
124 EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState()); 249 // write observer was invoked with its boolean parameter set to false.
125 ASSERT_TRUE(PathExists(writer.path())); 250 EXPECT_FALSE(successful_write_reply_observer_.GetAndResetObservationState());
126 EXPECT_EQ("foo", GetFileContent(writer.path())); 251 EXPECT_EQ(CALLED_WITH_ERROR,
127 252 write_callback_observer_.GetAndResetObservationState());
128 // Confirm that re-installing the observer works for another write. 253 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 } 254 }
148 255
149 TEST_F(ImportantFileWriterTest, ScheduleWrite) { 256 TEST_F(ImportantFileWriterTest, ScheduleWrite) {
150 ImportantFileWriter writer(file_, 257 ImportantFileWriter writer(file_,
151 ThreadTaskRunnerHandle::Get(), 258 ThreadTaskRunnerHandle::Get(),
152 TimeDelta::FromMilliseconds(25)); 259 TimeDelta::FromMilliseconds(25));
153 EXPECT_FALSE(writer.HasPendingWrite()); 260 EXPECT_FALSE(writer.HasPendingWrite());
154 DataSerializer serializer("foo"); 261 DataSerializer serializer("foo");
155 writer.ScheduleWrite(&serializer); 262 writer.ScheduleWrite(&serializer);
156 EXPECT_TRUE(writer.HasPendingWrite()); 263 EXPECT_TRUE(writer.HasPendingWrite());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 writer.ScheduleWrite(&baz); 296 writer.ScheduleWrite(&baz);
190 ThreadTaskRunnerHandle::Get()->PostDelayedTask( 297 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
191 FROM_HERE, MessageLoop::QuitWhenIdleClosure(), 298 FROM_HERE, MessageLoop::QuitWhenIdleClosure(),
192 TimeDelta::FromMilliseconds(100)); 299 TimeDelta::FromMilliseconds(100));
193 RunLoop().Run(); 300 RunLoop().Run();
194 ASSERT_TRUE(PathExists(writer.path())); 301 ASSERT_TRUE(PathExists(writer.path()));
195 EXPECT_EQ("baz", GetFileContent(writer.path())); 302 EXPECT_EQ("baz", GetFileContent(writer.path()));
196 } 303 }
197 304
198 } // namespace base 305 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698