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

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 a parameter name 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 class SynchronousWriteCallbackObserver {
85 public:
86 SynchronousWriteCallbackObserver()
87 : write_callback_observed_(false), write_callback_success_value_(false) {}
88
89 // Register on_write() to be called on the next write of |writer|.
90 void ObserveNextWriteCallback(ImportantFileWriter* writer);
91
92 struct WriteCallbackObservationState {
93 bool was_called;
94 bool success_param_value;
95 };
gab 2016/08/31 19:45:34 Use an enum instead of a struct to keep it to a si
proberge 2016/08/31 21:06:44 Done.
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_FALSE(write_callback_observed_);
104 write_callback_observed_ = true;
105 write_callback_success_value_ = success;
106 }
107
108 bool write_callback_observed_;
109 bool write_callback_success_value_;
110
111 DISALLOW_COPY_AND_ASSIGN(SynchronousWriteCallbackObserver);
112 };
113
114 void SynchronousWriteCallbackObserver::ObserveNextWriteCallback(
115 ImportantFileWriter* writer) {
116 writer->RegisterOnNextWriteSynchronousCallback(base::Bind(
117 &SynchronousWriteCallbackObserver::on_write, base::Unretained(this)));
118 }
119
120 SynchronousWriteCallbackObserver::WriteCallbackObservationState
121 SynchronousWriteCallbackObserver::GetAndResetObservationState() {
122 WriteCallbackObservationState observation_state;
123 observation_state.was_called = write_callback_observed_;
124 observation_state.success_param_value = write_callback_success_value_;
125 write_callback_observed_ = false;
126 return observation_state;
127 }
128
84 } // namespace 129 } // namespace
85 130
86 class ImportantFileWriterTest : public testing::Test { 131 class ImportantFileWriterTest : public testing::Test {
87 public: 132 public:
88 ImportantFileWriterTest() { } 133 ImportantFileWriterTest() { }
89 void SetUp() override { 134 void SetUp() override {
90 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 135 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
91 file_ = temp_dir_.path().AppendASCII("test-file"); 136 file_ = temp_dir_.path().AppendASCII("test-file");
92 } 137 }
93 138
94 protected: 139 protected:
95 SuccessfulWriteObserver successful_write_observer_; 140 SuccessfulWriteObserver successful_write_observer_;
141 SynchronousWriteCallbackObserver write_callback_observer_;
96 FilePath file_; 142 FilePath file_;
97 MessageLoop loop_; 143 MessageLoop loop_;
98 144
99 private: 145 private:
100 ScopedTempDir temp_dir_; 146 ScopedTempDir temp_dir_;
101 }; 147 };
102 148
103 TEST_F(ImportantFileWriterTest, Basic) { 149 TEST_F(ImportantFileWriterTest, Basic) {
104 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get()); 150 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
105 EXPECT_FALSE(PathExists(writer.path())); 151 EXPECT_FALSE(PathExists(writer.path()));
106 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 152 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
153 EXPECT_FALSE(
154 write_callback_observer_.GetAndResetObservationState().was_called);
107 writer.WriteNow(WrapUnique(new std::string("foo"))); 155 writer.WriteNow(WrapUnique(new std::string("foo")));
108 RunLoop().RunUntilIdle(); 156 RunLoop().RunUntilIdle();
109 157
110 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 158 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
159 EXPECT_FALSE(
160 write_callback_observer_.GetAndResetObservationState().was_called);
111 ASSERT_TRUE(PathExists(writer.path())); 161 ASSERT_TRUE(PathExists(writer.path()));
112 EXPECT_EQ("foo", GetFileContent(writer.path())); 162 EXPECT_EQ("foo", GetFileContent(writer.path()));
113 } 163 }
114 164
115 TEST_F(ImportantFileWriterTest, BasicWithSuccessfulWriteObserver) { 165 TEST_F(ImportantFileWriterTest, BasicWithWriteObservers) {
116 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get()); 166 ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
117 EXPECT_FALSE(PathExists(writer.path())); 167 EXPECT_FALSE(PathExists(writer.path()));
118 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 168 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
169 EXPECT_FALSE(
170 write_callback_observer_.GetAndResetObservationState().was_called);
119 successful_write_observer_.ObserveNextSuccessfulWrite(&writer); 171 successful_write_observer_.ObserveNextSuccessfulWrite(&writer);
172 write_callback_observer_.ObserveNextWriteCallback(&writer);
120 writer.WriteNow(WrapUnique(new std::string("foo"))); 173 writer.WriteNow(WrapUnique(new std::string("foo")));
121 RunLoop().RunUntilIdle(); 174 RunLoop().RunUntilIdle();
122 175
123 // Confirm that the observer is invoked. 176 // Confirm that the observers are invoked.
124 EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState()); 177 EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState());
178 SynchronousWriteCallbackObserver::WriteCallbackObservationState cb_state =
179 write_callback_observer_.GetAndResetObservationState();
180 EXPECT_TRUE(cb_state.was_called);
181 EXPECT_TRUE(cb_state.success_param_value);
125 ASSERT_TRUE(PathExists(writer.path())); 182 ASSERT_TRUE(PathExists(writer.path()));
126 EXPECT_EQ("foo", GetFileContent(writer.path())); 183 EXPECT_EQ("foo", GetFileContent(writer.path()));
127 184
128 // Confirm that re-installing the observer works for another write. 185 // Confirm that re-installing the observers works for another write.
129 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 186 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
187 EXPECT_FALSE(
188 write_callback_observer_.GetAndResetObservationState().was_called);
130 successful_write_observer_.ObserveNextSuccessfulWrite(&writer); 189 successful_write_observer_.ObserveNextSuccessfulWrite(&writer);
190 write_callback_observer_.ObserveNextWriteCallback(&writer);
131 writer.WriteNow(WrapUnique(new std::string("bar"))); 191 writer.WriteNow(WrapUnique(new std::string("bar")));
132 RunLoop().RunUntilIdle(); 192 RunLoop().RunUntilIdle();
133 193
134 EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState()); 194 EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState());
195 cb_state = write_callback_observer_.GetAndResetObservationState();
gab 2016/08/31 19:45:34 The |write_callback_observer_| should have been ca
proberge 2016/08/31 21:06:44 Not quite. WriteNow() uses PostTaskAndReply to Wri
gab 2016/09/01 19:59:53 I see, then the way to split this is to bind Impor
proberge 2016/09/07 19:07:15 Done.
196 EXPECT_TRUE(cb_state.was_called);
197 EXPECT_TRUE(cb_state.success_param_value);
135 ASSERT_TRUE(PathExists(writer.path())); 198 ASSERT_TRUE(PathExists(writer.path()));
136 EXPECT_EQ("bar", GetFileContent(writer.path())); 199 EXPECT_EQ("bar", GetFileContent(writer.path()));
137 200
138 // Confirm that writing again without re-installing the observer doesn't 201 // Confirm that writing again without re-installing the observers doesn't
139 // result in a notification. 202 // result in a notification.
140 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 203 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
204 EXPECT_FALSE(
205 write_callback_observer_.GetAndResetObservationState().was_called);
141 writer.WriteNow(WrapUnique(new std::string("baz"))); 206 writer.WriteNow(WrapUnique(new std::string("baz")));
142 RunLoop().RunUntilIdle(); 207 RunLoop().RunUntilIdle();
143 208
144 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); 209 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
210 EXPECT_FALSE(
211 write_callback_observer_.GetAndResetObservationState().was_called);
145 ASSERT_TRUE(PathExists(writer.path())); 212 ASSERT_TRUE(PathExists(writer.path()));
146 EXPECT_EQ("baz", GetFileContent(writer.path())); 213 EXPECT_EQ("baz", GetFileContent(writer.path()));
147 } 214 }
148 215
216 TEST_F(ImportantFileWriterTest, FailedWriteWithWriteObservers) {
217 // Use an invalid file path to get a FILE_ERROR_ACCESS_DENIED error when
218 // trying to write the file.
219 ImportantFileWriter writer(FilePath().AppendASCII("bad/../path"),
gab 2016/08/31 19:45:34 The ".." here merely makes this more likely to not
proberge 2016/08/31 21:06:44 This is actually a hack to make WriteFileAtomicall
gab 2016/09/01 19:59:53 Ah ok I see, then (1.) is best IMO, but clarify th
proberge 2016/09/07 19:07:15 Done.
220 ThreadTaskRunnerHandle::Get());
221 EXPECT_FALSE(PathExists(writer.path()));
222 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
223 EXPECT_FALSE(
224 write_callback_observer_.GetAndResetObservationState().was_called);
225 successful_write_observer_.ObserveNextSuccessfulWrite(&writer);
226 write_callback_observer_.ObserveNextWriteCallback(&writer);
227 writer.WriteNow(WrapUnique(new std::string("foo")));
228 RunLoop().RunUntilIdle();
229
230 // Confirm that the successful write observer was not invoked, and that the
231 // write observer was invoked with its boolean parameter set to false.
232 EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
233 SynchronousWriteCallbackObserver::WriteCallbackObservationState cb_state =
234 write_callback_observer_.GetAndResetObservationState();
235 EXPECT_TRUE(cb_state.was_called);
236 EXPECT_FALSE(cb_state.success_param_value);
237 EXPECT_FALSE(PathExists(writer.path()));
238 }
239
149 TEST_F(ImportantFileWriterTest, ScheduleWrite) { 240 TEST_F(ImportantFileWriterTest, ScheduleWrite) {
150 ImportantFileWriter writer(file_, 241 ImportantFileWriter writer(file_,
151 ThreadTaskRunnerHandle::Get(), 242 ThreadTaskRunnerHandle::Get(),
152 TimeDelta::FromMilliseconds(25)); 243 TimeDelta::FromMilliseconds(25));
153 EXPECT_FALSE(writer.HasPendingWrite()); 244 EXPECT_FALSE(writer.HasPendingWrite());
154 DataSerializer serializer("foo"); 245 DataSerializer serializer("foo");
155 writer.ScheduleWrite(&serializer); 246 writer.ScheduleWrite(&serializer);
156 EXPECT_TRUE(writer.HasPendingWrite()); 247 EXPECT_TRUE(writer.HasPendingWrite());
157 ThreadTaskRunnerHandle::Get()->PostDelayedTask( 248 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
158 FROM_HERE, MessageLoop::QuitWhenIdleClosure(), 249 FROM_HERE, MessageLoop::QuitWhenIdleClosure(),
(...skipping 30 matching lines...) Expand all
189 writer.ScheduleWrite(&baz); 280 writer.ScheduleWrite(&baz);
190 ThreadTaskRunnerHandle::Get()->PostDelayedTask( 281 ThreadTaskRunnerHandle::Get()->PostDelayedTask(
191 FROM_HERE, MessageLoop::QuitWhenIdleClosure(), 282 FROM_HERE, MessageLoop::QuitWhenIdleClosure(),
192 TimeDelta::FromMilliseconds(100)); 283 TimeDelta::FromMilliseconds(100));
193 RunLoop().Run(); 284 RunLoop().Run();
194 ASSERT_TRUE(PathExists(writer.path())); 285 ASSERT_TRUE(PathExists(writer.path()));
195 EXPECT_EQ("baz", GetFileContent(writer.path())); 286 EXPECT_EQ("baz", GetFileContent(writer.path()));
196 } 287 }
197 288
198 } // namespace base 289 } // 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