OLD | NEW |
| (Empty) |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "webkit/browser/fileapi/quota/quota_reservation_manager.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/file_util.h" | |
10 #include "base/files/file.h" | |
11 #include "base/files/scoped_temp_dir.h" | |
12 #include "base/message_loop/message_loop.h" | |
13 #include "base/run_loop.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 #include "webkit/browser/fileapi/quota/open_file_handle.h" | |
16 #include "webkit/browser/fileapi/quota/quota_reservation.h" | |
17 | |
18 namespace fileapi { | |
19 | |
20 namespace { | |
21 | |
22 const char kOrigin[] = "http://example.com"; | |
23 const FileSystemType kType = kFileSystemTypeTemporary; | |
24 const int64 kInitialFileSize = 1; | |
25 | |
26 typedef QuotaReservationManager::ReserveQuotaCallback ReserveQuotaCallback; | |
27 | |
28 int64 GetFileSize(const base::FilePath& path) { | |
29 int64 size = 0; | |
30 base::GetFileSize(path, &size); | |
31 return size; | |
32 } | |
33 | |
34 void SetFileSize(const base::FilePath& path, int64 size) { | |
35 base::File file(path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE); | |
36 ASSERT_TRUE(file.IsValid()); | |
37 ASSERT_TRUE(file.SetLength(size)); | |
38 } | |
39 | |
40 class FakeBackend : public QuotaReservationManager::QuotaBackend { | |
41 public: | |
42 FakeBackend() | |
43 : on_memory_usage_(kInitialFileSize), | |
44 on_disk_usage_(kInitialFileSize) {} | |
45 virtual ~FakeBackend() {} | |
46 | |
47 virtual void ReserveQuota(const GURL& origin, | |
48 FileSystemType type, | |
49 int64 delta, | |
50 const ReserveQuotaCallback& callback) OVERRIDE { | |
51 EXPECT_EQ(GURL(kOrigin), origin); | |
52 EXPECT_EQ(kType, type); | |
53 on_memory_usage_ += delta; | |
54 base::MessageLoopProxy::current()->PostTask( | |
55 FROM_HERE, | |
56 base::Bind(base::IgnoreResult(callback), base::File::FILE_OK, delta)); | |
57 } | |
58 | |
59 virtual void ReleaseReservedQuota(const GURL& origin, | |
60 FileSystemType type, | |
61 int64 size) OVERRIDE { | |
62 EXPECT_LE(0, size); | |
63 EXPECT_EQ(GURL(kOrigin), origin); | |
64 EXPECT_EQ(kType, type); | |
65 on_memory_usage_ -= size; | |
66 } | |
67 | |
68 virtual void CommitQuotaUsage(const GURL& origin, | |
69 FileSystemType type, | |
70 int64 delta) OVERRIDE { | |
71 EXPECT_EQ(GURL(kOrigin), origin); | |
72 EXPECT_EQ(kType, type); | |
73 on_disk_usage_ += delta; | |
74 on_memory_usage_ += delta; | |
75 } | |
76 | |
77 virtual void IncrementDirtyCount(const GURL& origin, | |
78 FileSystemType type) OVERRIDE {} | |
79 virtual void DecrementDirtyCount(const GURL& origin, | |
80 FileSystemType type) OVERRIDE {} | |
81 | |
82 int64 on_memory_usage() { return on_memory_usage_; } | |
83 int64 on_disk_usage() { return on_disk_usage_; } | |
84 | |
85 private: | |
86 int64 on_memory_usage_; | |
87 int64 on_disk_usage_; | |
88 | |
89 DISALLOW_COPY_AND_ASSIGN(FakeBackend); | |
90 }; | |
91 | |
92 class FakeWriter { | |
93 public: | |
94 explicit FakeWriter(scoped_ptr<OpenFileHandle> handle) | |
95 : handle_(handle.Pass()), | |
96 path_(handle_->platform_path()), | |
97 max_written_offset_(handle_->GetEstimatedFileSize()), | |
98 append_mode_write_amount_(0), | |
99 dirty_(false) { | |
100 } | |
101 | |
102 ~FakeWriter() { | |
103 if (handle_) | |
104 EXPECT_FALSE(dirty_); | |
105 } | |
106 | |
107 int64 Truncate(int64 length) { | |
108 int64 consumed = 0; | |
109 | |
110 if (max_written_offset_ < length) { | |
111 consumed = length - max_written_offset_; | |
112 max_written_offset_ = length; | |
113 } | |
114 SetFileSize(path_, length); | |
115 return consumed; | |
116 } | |
117 | |
118 int64 Write(int64 max_offset) { | |
119 dirty_ = true; | |
120 | |
121 int64 consumed = 0; | |
122 if (max_written_offset_ < max_offset) { | |
123 consumed = max_offset - max_written_offset_; | |
124 max_written_offset_ = max_offset; | |
125 } | |
126 if (GetFileSize(path_) < max_offset) | |
127 SetFileSize(path_, max_offset); | |
128 return consumed; | |
129 } | |
130 | |
131 int64 Append(int64 amount) { | |
132 dirty_ = true; | |
133 append_mode_write_amount_ += amount; | |
134 SetFileSize(path_, GetFileSize(path_) + amount); | |
135 return amount; | |
136 } | |
137 | |
138 void ReportUsage() { | |
139 handle_->UpdateMaxWrittenOffset(max_written_offset_); | |
140 handle_->AddAppendModeWriteAmount(append_mode_write_amount_); | |
141 max_written_offset_ = handle_->GetEstimatedFileSize(); | |
142 append_mode_write_amount_ = 0; | |
143 dirty_ = false; | |
144 } | |
145 | |
146 void ClearWithoutUsageReport() { | |
147 handle_.reset(); | |
148 } | |
149 | |
150 private: | |
151 scoped_ptr<OpenFileHandle> handle_; | |
152 base::FilePath path_; | |
153 int64 max_written_offset_; | |
154 int64 append_mode_write_amount_; | |
155 bool dirty_; | |
156 }; | |
157 | |
158 void ExpectSuccess(bool* done, base::File::Error error) { | |
159 EXPECT_FALSE(*done); | |
160 *done = true; | |
161 EXPECT_EQ(base::File::FILE_OK, error); | |
162 } | |
163 | |
164 void RefreshReservation(QuotaReservation* reservation, int64 size) { | |
165 DCHECK(reservation); | |
166 | |
167 bool done = false; | |
168 reservation->RefreshReservation(size, base::Bind(&ExpectSuccess, &done)); | |
169 base::RunLoop().RunUntilIdle(); | |
170 EXPECT_TRUE(done); | |
171 } | |
172 | |
173 } // namespace | |
174 | |
175 class QuotaReservationManagerTest : public testing::Test { | |
176 public: | |
177 QuotaReservationManagerTest() {} | |
178 virtual ~QuotaReservationManagerTest() {} | |
179 | |
180 virtual void SetUp() OVERRIDE { | |
181 ASSERT_TRUE(work_dir_.CreateUniqueTempDir()); | |
182 file_path_ = work_dir_.path().Append(FILE_PATH_LITERAL("hoge")); | |
183 SetFileSize(file_path_, kInitialFileSize); | |
184 | |
185 scoped_ptr<QuotaReservationManager::QuotaBackend> backend(new FakeBackend); | |
186 reservation_manager_.reset(new QuotaReservationManager(backend.Pass())); | |
187 } | |
188 | |
189 virtual void TearDown() OVERRIDE { | |
190 reservation_manager_.reset(); | |
191 } | |
192 | |
193 FakeBackend* fake_backend() { | |
194 return static_cast<FakeBackend*>(reservation_manager_->backend_.get()); | |
195 } | |
196 | |
197 QuotaReservationManager* reservation_manager() { | |
198 return reservation_manager_.get(); | |
199 } | |
200 | |
201 const base::FilePath& file_path() const { | |
202 return file_path_; | |
203 } | |
204 | |
205 private: | |
206 base::MessageLoop message_loop_; | |
207 base::ScopedTempDir work_dir_; | |
208 base::FilePath file_path_; | |
209 scoped_ptr<QuotaReservationManager> reservation_manager_; | |
210 | |
211 DISALLOW_COPY_AND_ASSIGN(QuotaReservationManagerTest); | |
212 }; | |
213 | |
214 TEST_F(QuotaReservationManagerTest, BasicTest) { | |
215 scoped_refptr<QuotaReservation> reservation = | |
216 reservation_manager()->CreateReservation(GURL(kOrigin), kType); | |
217 | |
218 { | |
219 RefreshReservation(reservation.get(), 10 + 20 + 3); | |
220 int64 cached_reserved_quota = reservation->remaining_quota(); | |
221 FakeWriter writer(reservation->GetOpenFileHandle(file_path())); | |
222 | |
223 cached_reserved_quota -= writer.Write(kInitialFileSize + 10); | |
224 EXPECT_LE(0, cached_reserved_quota); | |
225 cached_reserved_quota -= writer.Append(20); | |
226 EXPECT_LE(0, cached_reserved_quota); | |
227 | |
228 writer.ReportUsage(); | |
229 } | |
230 | |
231 EXPECT_EQ(3, reservation->remaining_quota()); | |
232 EXPECT_EQ(kInitialFileSize + 10 + 20, GetFileSize(file_path())); | |
233 EXPECT_EQ(kInitialFileSize + 10 + 20, fake_backend()->on_disk_usage()); | |
234 EXPECT_EQ(kInitialFileSize + 10 + 20 + 3, fake_backend()->on_memory_usage()); | |
235 | |
236 { | |
237 RefreshReservation(reservation.get(), 5); | |
238 FakeWriter writer(reservation->GetOpenFileHandle(file_path())); | |
239 | |
240 EXPECT_EQ(0, writer.Truncate(3)); | |
241 | |
242 writer.ReportUsage(); | |
243 } | |
244 | |
245 EXPECT_EQ(5, reservation->remaining_quota()); | |
246 EXPECT_EQ(3, GetFileSize(file_path())); | |
247 EXPECT_EQ(3, fake_backend()->on_disk_usage()); | |
248 EXPECT_EQ(3 + 5, fake_backend()->on_memory_usage()); | |
249 | |
250 reservation = NULL; | |
251 | |
252 EXPECT_EQ(3, fake_backend()->on_memory_usage()); | |
253 } | |
254 | |
255 TEST_F(QuotaReservationManagerTest, MultipleWriter) { | |
256 scoped_refptr<QuotaReservation> reservation = | |
257 reservation_manager()->CreateReservation(GURL(kOrigin), kType); | |
258 | |
259 { | |
260 RefreshReservation(reservation.get(), 10 + 20 + 30 + 40 + 5); | |
261 int64 cached_reserved_quota = reservation->remaining_quota(); | |
262 FakeWriter writer1(reservation->GetOpenFileHandle(file_path())); | |
263 FakeWriter writer2(reservation->GetOpenFileHandle(file_path())); | |
264 FakeWriter writer3(reservation->GetOpenFileHandle(file_path())); | |
265 | |
266 cached_reserved_quota -= writer1.Write(kInitialFileSize + 10); | |
267 EXPECT_LE(0, cached_reserved_quota); | |
268 cached_reserved_quota -= writer2.Write(kInitialFileSize + 20); | |
269 cached_reserved_quota -= writer3.Append(30); | |
270 EXPECT_LE(0, cached_reserved_quota); | |
271 cached_reserved_quota -= writer3.Append(40); | |
272 EXPECT_LE(0, cached_reserved_quota); | |
273 | |
274 writer1.ReportUsage(); | |
275 writer2.ReportUsage(); | |
276 writer3.ReportUsage(); | |
277 } | |
278 | |
279 EXPECT_EQ(kInitialFileSize + 20 + 30 + 40, GetFileSize(file_path())); | |
280 EXPECT_EQ(kInitialFileSize + 10 + 20 + 30 + 40 + 5, | |
281 fake_backend()->on_memory_usage()); | |
282 EXPECT_EQ(kInitialFileSize + 20 + 30 + 40, fake_backend()->on_disk_usage()); | |
283 | |
284 reservation = NULL; | |
285 | |
286 EXPECT_EQ(kInitialFileSize + 20 + 30 + 40, fake_backend()->on_disk_usage()); | |
287 } | |
288 | |
289 TEST_F(QuotaReservationManagerTest, MultipleClient) { | |
290 scoped_refptr<QuotaReservation> reservation1 = | |
291 reservation_manager()->CreateReservation(GURL(kOrigin), kType); | |
292 RefreshReservation(reservation1, 10); | |
293 int64 cached_reserved_quota1 = reservation1->remaining_quota(); | |
294 | |
295 scoped_refptr<QuotaReservation> reservation2 = | |
296 reservation_manager()->CreateReservation(GURL(kOrigin), kType); | |
297 RefreshReservation(reservation2, 20); | |
298 int64 cached_reserved_quota2 = reservation2->remaining_quota(); | |
299 | |
300 scoped_ptr<FakeWriter> writer1( | |
301 new FakeWriter(reservation1->GetOpenFileHandle(file_path()))); | |
302 | |
303 scoped_ptr<FakeWriter> writer2( | |
304 new FakeWriter(reservation2->GetOpenFileHandle(file_path()))); | |
305 | |
306 cached_reserved_quota1 -= writer1->Write(kInitialFileSize + 10); | |
307 EXPECT_LE(0, cached_reserved_quota1); | |
308 | |
309 cached_reserved_quota2 -= writer2->Append(20); | |
310 EXPECT_LE(0, cached_reserved_quota2); | |
311 | |
312 writer1->ReportUsage(); | |
313 RefreshReservation(reservation1.get(), 2); | |
314 cached_reserved_quota1 = reservation1->remaining_quota(); | |
315 | |
316 writer2->ReportUsage(); | |
317 RefreshReservation(reservation2.get(), 3); | |
318 cached_reserved_quota2 = reservation2->remaining_quota(); | |
319 | |
320 writer1.reset(); | |
321 writer2.reset(); | |
322 | |
323 EXPECT_EQ(kInitialFileSize + 10 + 20, GetFileSize(file_path())); | |
324 EXPECT_EQ(kInitialFileSize + 10 + 20 + 2 + 3, | |
325 fake_backend()->on_memory_usage()); | |
326 EXPECT_EQ(kInitialFileSize + 10 + 20, fake_backend()->on_disk_usage()); | |
327 | |
328 reservation1 = NULL; | |
329 EXPECT_EQ(kInitialFileSize + 10 + 20 + 3, fake_backend()->on_memory_usage()); | |
330 | |
331 reservation2 = NULL; | |
332 EXPECT_EQ(kInitialFileSize + 10 + 20, fake_backend()->on_memory_usage()); | |
333 } | |
334 | |
335 TEST_F(QuotaReservationManagerTest, ClientCrash) { | |
336 scoped_refptr<QuotaReservation> reservation1 = | |
337 reservation_manager()->CreateReservation(GURL(kOrigin), kType); | |
338 RefreshReservation(reservation1.get(), 15); | |
339 | |
340 scoped_refptr<QuotaReservation> reservation2 = | |
341 reservation_manager()->CreateReservation(GURL(kOrigin), kType); | |
342 RefreshReservation(reservation2.get(), 20); | |
343 | |
344 { | |
345 FakeWriter writer(reservation1->GetOpenFileHandle(file_path())); | |
346 | |
347 writer.Write(kInitialFileSize + 10); | |
348 | |
349 reservation1->OnClientCrash(); | |
350 writer.ClearWithoutUsageReport(); | |
351 } | |
352 reservation1 = NULL; | |
353 | |
354 EXPECT_EQ(kInitialFileSize + 10, GetFileSize(file_path())); | |
355 EXPECT_EQ(kInitialFileSize + 15 + 20, fake_backend()->on_memory_usage()); | |
356 EXPECT_EQ(kInitialFileSize + 10, fake_backend()->on_disk_usage()); | |
357 | |
358 reservation2 = NULL; | |
359 EXPECT_EQ(kInitialFileSize + 10, fake_backend()->on_memory_usage()); | |
360 } | |
361 | |
362 } // namespace fileapi | |
OLD | NEW |