1 // Copyright 2014 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.
5 #include "storage/browser/fileapi/quota/quota_reservation_manager.h"
8 #include "base/bind_helpers.h"
9 #include "base/files/file.h"
10 #include "base/files/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/location.h"
13 #include "base/run_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "storage/browser/fileapi/quota/open_file_handle.h"
17 #include "storage/browser/fileapi/quota/quota_reservation.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 using storage::kFileSystemTypeTemporary
;
21 using storage::OpenFileHandle
;
22 using storage::QuotaReservation
;
23 using storage::QuotaReservationManager
;
29 const char kOrigin
[] = "http://example.com";
30 const storage::FileSystemType kType
= kFileSystemTypeTemporary
;
31 const int64 kInitialFileSize
= 1;
33 typedef QuotaReservationManager::ReserveQuotaCallback ReserveQuotaCallback
;
35 int64
GetFileSize(const base::FilePath
& path
) {
37 base::GetFileSize(path
, &size
);
41 void SetFileSize(const base::FilePath
& path
, int64 size
) {
42 base::File
file(path
, base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_WRITE
);
43 ASSERT_TRUE(file
.IsValid());
44 ASSERT_TRUE(file
.SetLength(size
));
47 class FakeBackend
: public QuotaReservationManager::QuotaBackend
{
50 : on_memory_usage_(kInitialFileSize
),
51 on_disk_usage_(kInitialFileSize
) {}
52 ~FakeBackend() override
{}
54 void ReserveQuota(const GURL
& origin
,
55 storage::FileSystemType type
,
57 const ReserveQuotaCallback
& callback
) override
{
58 EXPECT_EQ(GURL(kOrigin
), origin
);
59 EXPECT_EQ(kType
, type
);
60 on_memory_usage_
+= delta
;
61 base::ThreadTaskRunnerHandle::Get()->PostTask(
63 base::Bind(base::IgnoreResult(callback
), base::File::FILE_OK
, delta
));
66 void ReleaseReservedQuota(const GURL
& origin
,
67 storage::FileSystemType type
,
68 int64 size
) override
{
70 EXPECT_EQ(GURL(kOrigin
), origin
);
71 EXPECT_EQ(kType
, type
);
72 on_memory_usage_
-= size
;
75 void CommitQuotaUsage(const GURL
& origin
,
76 storage::FileSystemType type
,
77 int64 delta
) override
{
78 EXPECT_EQ(GURL(kOrigin
), origin
);
79 EXPECT_EQ(kType
, type
);
80 on_disk_usage_
+= delta
;
81 on_memory_usage_
+= delta
;
84 void IncrementDirtyCount(const GURL
& origin
,
85 storage::FileSystemType type
) override
{}
86 void DecrementDirtyCount(const GURL
& origin
,
87 storage::FileSystemType type
) override
{}
89 int64
on_memory_usage() { return on_memory_usage_
; }
90 int64
on_disk_usage() { return on_disk_usage_
; }
93 int64 on_memory_usage_
;
96 DISALLOW_COPY_AND_ASSIGN(FakeBackend
);
101 explicit FakeWriter(scoped_ptr
<OpenFileHandle
> handle
)
102 : handle_(handle
.Pass()),
103 path_(handle_
->platform_path()),
104 max_written_offset_(handle_
->GetEstimatedFileSize()),
105 append_mode_write_amount_(0),
111 EXPECT_FALSE(dirty_
);
114 int64
Truncate(int64 length
) {
117 if (max_written_offset_
< length
) {
118 consumed
= length
- max_written_offset_
;
119 max_written_offset_
= length
;
121 SetFileSize(path_
, length
);
125 int64
Write(int64 max_offset
) {
129 if (max_written_offset_
< max_offset
) {
130 consumed
= max_offset
- max_written_offset_
;
131 max_written_offset_
= max_offset
;
133 if (GetFileSize(path_
) < max_offset
)
134 SetFileSize(path_
, max_offset
);
138 int64
Append(int64 amount
) {
140 append_mode_write_amount_
+= amount
;
141 SetFileSize(path_
, GetFileSize(path_
) + amount
);
146 handle_
->UpdateMaxWrittenOffset(max_written_offset_
);
147 handle_
->AddAppendModeWriteAmount(append_mode_write_amount_
);
148 max_written_offset_
= handle_
->GetEstimatedFileSize();
149 append_mode_write_amount_
= 0;
153 void ClearWithoutUsageReport() {
158 scoped_ptr
<OpenFileHandle
> handle_
;
159 base::FilePath path_
;
160 int64 max_written_offset_
;
161 int64 append_mode_write_amount_
;
165 void ExpectSuccess(bool* done
, base::File::Error error
) {
168 EXPECT_EQ(base::File::FILE_OK
, error
);
171 void RefreshReservation(QuotaReservation
* reservation
, int64 size
) {
175 reservation
->RefreshReservation(size
, base::Bind(&ExpectSuccess
, &done
));
176 base::RunLoop().RunUntilIdle();
182 class QuotaReservationManagerTest
: public testing::Test
{
184 QuotaReservationManagerTest() {}
185 ~QuotaReservationManagerTest() override
{}
187 void SetUp() override
{
188 ASSERT_TRUE(work_dir_
.CreateUniqueTempDir());
189 file_path_
= work_dir_
.path().Append(FILE_PATH_LITERAL("hoge"));
190 SetFileSize(file_path_
, kInitialFileSize
);
192 scoped_ptr
<QuotaReservationManager::QuotaBackend
> backend(new FakeBackend
);
193 reservation_manager_
.reset(new QuotaReservationManager(backend
.Pass()));
196 void TearDown() override
{ reservation_manager_
.reset(); }
198 FakeBackend
* fake_backend() {
199 return static_cast<FakeBackend
*>(reservation_manager_
->backend_
.get());
202 QuotaReservationManager
* reservation_manager() {
203 return reservation_manager_
.get();
206 const base::FilePath
& file_path() const {
211 base::MessageLoop message_loop_
;
212 base::ScopedTempDir work_dir_
;
213 base::FilePath file_path_
;
214 scoped_ptr
<QuotaReservationManager
> reservation_manager_
;
216 DISALLOW_COPY_AND_ASSIGN(QuotaReservationManagerTest
);
219 TEST_F(QuotaReservationManagerTest
, BasicTest
) {
220 scoped_refptr
<QuotaReservation
> reservation
=
221 reservation_manager()->CreateReservation(GURL(kOrigin
), kType
);
224 RefreshReservation(reservation
.get(), 10 + 20 + 3);
225 int64 cached_reserved_quota
= reservation
->remaining_quota();
226 FakeWriter
writer(reservation
->GetOpenFileHandle(file_path()));
228 cached_reserved_quota
-= writer
.Write(kInitialFileSize
+ 10);
229 EXPECT_LE(0, cached_reserved_quota
);
230 cached_reserved_quota
-= writer
.Append(20);
231 EXPECT_LE(0, cached_reserved_quota
);
233 writer
.ReportUsage();
236 EXPECT_EQ(3, reservation
->remaining_quota());
237 EXPECT_EQ(kInitialFileSize
+ 10 + 20, GetFileSize(file_path()));
238 EXPECT_EQ(kInitialFileSize
+ 10 + 20, fake_backend()->on_disk_usage());
239 EXPECT_EQ(kInitialFileSize
+ 10 + 20 + 3, fake_backend()->on_memory_usage());
242 RefreshReservation(reservation
.get(), 5);
243 FakeWriter
writer(reservation
->GetOpenFileHandle(file_path()));
245 EXPECT_EQ(0, writer
.Truncate(3));
247 writer
.ReportUsage();
250 EXPECT_EQ(5, reservation
->remaining_quota());
251 EXPECT_EQ(3, GetFileSize(file_path()));
252 EXPECT_EQ(3, fake_backend()->on_disk_usage());
253 EXPECT_EQ(3 + 5, fake_backend()->on_memory_usage());
257 EXPECT_EQ(3, fake_backend()->on_memory_usage());
260 TEST_F(QuotaReservationManagerTest
, MultipleWriter
) {
261 scoped_refptr
<QuotaReservation
> reservation
=
262 reservation_manager()->CreateReservation(GURL(kOrigin
), kType
);
265 RefreshReservation(reservation
.get(), 10 + 20 + 30 + 40 + 5);
266 int64 cached_reserved_quota
= reservation
->remaining_quota();
267 FakeWriter
writer1(reservation
->GetOpenFileHandle(file_path()));
268 FakeWriter
writer2(reservation
->GetOpenFileHandle(file_path()));
269 FakeWriter
writer3(reservation
->GetOpenFileHandle(file_path()));
271 cached_reserved_quota
-= writer1
.Write(kInitialFileSize
+ 10);
272 EXPECT_LE(0, cached_reserved_quota
);
273 cached_reserved_quota
-= writer2
.Write(kInitialFileSize
+ 20);
274 cached_reserved_quota
-= writer3
.Append(30);
275 EXPECT_LE(0, cached_reserved_quota
);
276 cached_reserved_quota
-= writer3
.Append(40);
277 EXPECT_LE(0, cached_reserved_quota
);
279 writer1
.ReportUsage();
280 writer2
.ReportUsage();
281 writer3
.ReportUsage();
284 EXPECT_EQ(kInitialFileSize
+ 20 + 30 + 40, GetFileSize(file_path()));
285 EXPECT_EQ(kInitialFileSize
+ 10 + 20 + 30 + 40 + 5,
286 fake_backend()->on_memory_usage());
287 EXPECT_EQ(kInitialFileSize
+ 20 + 30 + 40, fake_backend()->on_disk_usage());
291 EXPECT_EQ(kInitialFileSize
+ 20 + 30 + 40, fake_backend()->on_disk_usage());
294 TEST_F(QuotaReservationManagerTest
, MultipleClient
) {
295 scoped_refptr
<QuotaReservation
> reservation1
=
296 reservation_manager()->CreateReservation(GURL(kOrigin
), kType
);
297 RefreshReservation(reservation1
.get(), 10);
298 int64 cached_reserved_quota1
= reservation1
->remaining_quota();
300 scoped_refptr
<QuotaReservation
> reservation2
=
301 reservation_manager()->CreateReservation(GURL(kOrigin
), kType
);
302 RefreshReservation(reservation2
.get(), 20);
303 int64 cached_reserved_quota2
= reservation2
->remaining_quota();
305 scoped_ptr
<FakeWriter
> writer1(
306 new FakeWriter(reservation1
->GetOpenFileHandle(file_path())));
308 scoped_ptr
<FakeWriter
> writer2(
309 new FakeWriter(reservation2
->GetOpenFileHandle(file_path())));
311 cached_reserved_quota1
-= writer1
->Write(kInitialFileSize
+ 10);
312 EXPECT_LE(0, cached_reserved_quota1
);
314 cached_reserved_quota2
-= writer2
->Append(20);
315 EXPECT_LE(0, cached_reserved_quota2
);
317 writer1
->ReportUsage();
318 RefreshReservation(reservation1
.get(), 2);
319 cached_reserved_quota1
= reservation1
->remaining_quota();
321 writer2
->ReportUsage();
322 RefreshReservation(reservation2
.get(), 3);
323 cached_reserved_quota2
= reservation2
->remaining_quota();
328 EXPECT_EQ(kInitialFileSize
+ 10 + 20, GetFileSize(file_path()));
329 EXPECT_EQ(kInitialFileSize
+ 10 + 20 + 2 + 3,
330 fake_backend()->on_memory_usage());
331 EXPECT_EQ(kInitialFileSize
+ 10 + 20, fake_backend()->on_disk_usage());
334 EXPECT_EQ(kInitialFileSize
+ 10 + 20 + 3, fake_backend()->on_memory_usage());
337 EXPECT_EQ(kInitialFileSize
+ 10 + 20, fake_backend()->on_memory_usage());
340 TEST_F(QuotaReservationManagerTest
, ClientCrash
) {
341 scoped_refptr
<QuotaReservation
> reservation1
=
342 reservation_manager()->CreateReservation(GURL(kOrigin
), kType
);
343 RefreshReservation(reservation1
.get(), 15);
345 scoped_refptr
<QuotaReservation
> reservation2
=
346 reservation_manager()->CreateReservation(GURL(kOrigin
), kType
);
347 RefreshReservation(reservation2
.get(), 20);
350 FakeWriter
writer(reservation1
->GetOpenFileHandle(file_path()));
352 writer
.Write(kInitialFileSize
+ 10);
354 reservation1
->OnClientCrash();
355 writer
.ClearWithoutUsageReport();
359 EXPECT_EQ(kInitialFileSize
+ 10, GetFileSize(file_path()));
360 EXPECT_EQ(kInitialFileSize
+ 15 + 20, fake_backend()->on_memory_usage());
361 EXPECT_EQ(kInitialFileSize
+ 10, fake_backend()->on_disk_usage());
364 EXPECT_EQ(kInitialFileSize
+ 10, fake_backend()->on_memory_usage());
367 } // namespace content