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/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "storage/browser/fileapi/quota/open_file_handle.h"
15 #include "storage/browser/fileapi/quota/quota_reservation.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 using storage::kFileSystemTypeTemporary
;
19 using storage::OpenFileHandle
;
20 using storage::QuotaReservation
;
21 using storage::QuotaReservationManager
;
27 const char kOrigin
[] = "http://example.com";
28 const storage::FileSystemType kType
= kFileSystemTypeTemporary
;
29 const int64 kInitialFileSize
= 1;
31 typedef QuotaReservationManager::ReserveQuotaCallback ReserveQuotaCallback
;
33 int64
GetFileSize(const base::FilePath
& path
) {
35 base::GetFileSize(path
, &size
);
39 void SetFileSize(const base::FilePath
& path
, int64 size
) {
40 base::File
file(path
, base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_WRITE
);
41 ASSERT_TRUE(file
.IsValid());
42 ASSERT_TRUE(file
.SetLength(size
));
45 class FakeBackend
: public QuotaReservationManager::QuotaBackend
{
48 : on_memory_usage_(kInitialFileSize
),
49 on_disk_usage_(kInitialFileSize
) {}
50 ~FakeBackend() override
{}
52 void ReserveQuota(const GURL
& origin
,
53 storage::FileSystemType type
,
55 const ReserveQuotaCallback
& callback
) override
{
56 EXPECT_EQ(GURL(kOrigin
), origin
);
57 EXPECT_EQ(kType
, type
);
58 on_memory_usage_
+= delta
;
59 base::MessageLoopProxy::current()->PostTask(
61 base::Bind(base::IgnoreResult(callback
), base::File::FILE_OK
, delta
));
64 void ReleaseReservedQuota(const GURL
& origin
,
65 storage::FileSystemType type
,
66 int64 size
) override
{
68 EXPECT_EQ(GURL(kOrigin
), origin
);
69 EXPECT_EQ(kType
, type
);
70 on_memory_usage_
-= size
;
73 void CommitQuotaUsage(const GURL
& origin
,
74 storage::FileSystemType type
,
75 int64 delta
) override
{
76 EXPECT_EQ(GURL(kOrigin
), origin
);
77 EXPECT_EQ(kType
, type
);
78 on_disk_usage_
+= delta
;
79 on_memory_usage_
+= delta
;
82 void IncrementDirtyCount(const GURL
& origin
,
83 storage::FileSystemType type
) override
{}
84 void DecrementDirtyCount(const GURL
& origin
,
85 storage::FileSystemType type
) override
{}
87 int64
on_memory_usage() { return on_memory_usage_
; }
88 int64
on_disk_usage() { return on_disk_usage_
; }
91 int64 on_memory_usage_
;
94 DISALLOW_COPY_AND_ASSIGN(FakeBackend
);
99 explicit FakeWriter(scoped_ptr
<OpenFileHandle
> handle
)
100 : handle_(handle
.Pass()),
101 path_(handle_
->platform_path()),
102 max_written_offset_(handle_
->GetEstimatedFileSize()),
103 append_mode_write_amount_(0),
109 EXPECT_FALSE(dirty_
);
112 int64
Truncate(int64 length
) {
115 if (max_written_offset_
< length
) {
116 consumed
= length
- max_written_offset_
;
117 max_written_offset_
= length
;
119 SetFileSize(path_
, length
);
123 int64
Write(int64 max_offset
) {
127 if (max_written_offset_
< max_offset
) {
128 consumed
= max_offset
- max_written_offset_
;
129 max_written_offset_
= max_offset
;
131 if (GetFileSize(path_
) < max_offset
)
132 SetFileSize(path_
, max_offset
);
136 int64
Append(int64 amount
) {
138 append_mode_write_amount_
+= amount
;
139 SetFileSize(path_
, GetFileSize(path_
) + amount
);
144 handle_
->UpdateMaxWrittenOffset(max_written_offset_
);
145 handle_
->AddAppendModeWriteAmount(append_mode_write_amount_
);
146 max_written_offset_
= handle_
->GetEstimatedFileSize();
147 append_mode_write_amount_
= 0;
151 void ClearWithoutUsageReport() {
156 scoped_ptr
<OpenFileHandle
> handle_
;
157 base::FilePath path_
;
158 int64 max_written_offset_
;
159 int64 append_mode_write_amount_
;
163 void ExpectSuccess(bool* done
, base::File::Error error
) {
166 EXPECT_EQ(base::File::FILE_OK
, error
);
169 void RefreshReservation(QuotaReservation
* reservation
, int64 size
) {
173 reservation
->RefreshReservation(size
, base::Bind(&ExpectSuccess
, &done
));
174 base::RunLoop().RunUntilIdle();
180 class QuotaReservationManagerTest
: public testing::Test
{
182 QuotaReservationManagerTest() {}
183 ~QuotaReservationManagerTest() override
{}
185 void SetUp() override
{
186 ASSERT_TRUE(work_dir_
.CreateUniqueTempDir());
187 file_path_
= work_dir_
.path().Append(FILE_PATH_LITERAL("hoge"));
188 SetFileSize(file_path_
, kInitialFileSize
);
190 scoped_ptr
<QuotaReservationManager::QuotaBackend
> backend(new FakeBackend
);
191 reservation_manager_
.reset(new QuotaReservationManager(backend
.Pass()));
194 void TearDown() override
{ reservation_manager_
.reset(); }
196 FakeBackend
* fake_backend() {
197 return static_cast<FakeBackend
*>(reservation_manager_
->backend_
.get());
200 QuotaReservationManager
* reservation_manager() {
201 return reservation_manager_
.get();
204 const base::FilePath
& file_path() const {
209 base::MessageLoop message_loop_
;
210 base::ScopedTempDir work_dir_
;
211 base::FilePath file_path_
;
212 scoped_ptr
<QuotaReservationManager
> reservation_manager_
;
214 DISALLOW_COPY_AND_ASSIGN(QuotaReservationManagerTest
);
217 TEST_F(QuotaReservationManagerTest
, BasicTest
) {
218 scoped_refptr
<QuotaReservation
> reservation
=
219 reservation_manager()->CreateReservation(GURL(kOrigin
), kType
);
222 RefreshReservation(reservation
.get(), 10 + 20 + 3);
223 int64 cached_reserved_quota
= reservation
->remaining_quota();
224 FakeWriter
writer(reservation
->GetOpenFileHandle(file_path()));
226 cached_reserved_quota
-= writer
.Write(kInitialFileSize
+ 10);
227 EXPECT_LE(0, cached_reserved_quota
);
228 cached_reserved_quota
-= writer
.Append(20);
229 EXPECT_LE(0, cached_reserved_quota
);
231 writer
.ReportUsage();
234 EXPECT_EQ(3, reservation
->remaining_quota());
235 EXPECT_EQ(kInitialFileSize
+ 10 + 20, GetFileSize(file_path()));
236 EXPECT_EQ(kInitialFileSize
+ 10 + 20, fake_backend()->on_disk_usage());
237 EXPECT_EQ(kInitialFileSize
+ 10 + 20 + 3, fake_backend()->on_memory_usage());
240 RefreshReservation(reservation
.get(), 5);
241 FakeWriter
writer(reservation
->GetOpenFileHandle(file_path()));
243 EXPECT_EQ(0, writer
.Truncate(3));
245 writer
.ReportUsage();
248 EXPECT_EQ(5, reservation
->remaining_quota());
249 EXPECT_EQ(3, GetFileSize(file_path()));
250 EXPECT_EQ(3, fake_backend()->on_disk_usage());
251 EXPECT_EQ(3 + 5, fake_backend()->on_memory_usage());
255 EXPECT_EQ(3, fake_backend()->on_memory_usage());
258 TEST_F(QuotaReservationManagerTest
, MultipleWriter
) {
259 scoped_refptr
<QuotaReservation
> reservation
=
260 reservation_manager()->CreateReservation(GURL(kOrigin
), kType
);
263 RefreshReservation(reservation
.get(), 10 + 20 + 30 + 40 + 5);
264 int64 cached_reserved_quota
= reservation
->remaining_quota();
265 FakeWriter
writer1(reservation
->GetOpenFileHandle(file_path()));
266 FakeWriter
writer2(reservation
->GetOpenFileHandle(file_path()));
267 FakeWriter
writer3(reservation
->GetOpenFileHandle(file_path()));
269 cached_reserved_quota
-= writer1
.Write(kInitialFileSize
+ 10);
270 EXPECT_LE(0, cached_reserved_quota
);
271 cached_reserved_quota
-= writer2
.Write(kInitialFileSize
+ 20);
272 cached_reserved_quota
-= writer3
.Append(30);
273 EXPECT_LE(0, cached_reserved_quota
);
274 cached_reserved_quota
-= writer3
.Append(40);
275 EXPECT_LE(0, cached_reserved_quota
);
277 writer1
.ReportUsage();
278 writer2
.ReportUsage();
279 writer3
.ReportUsage();
282 EXPECT_EQ(kInitialFileSize
+ 20 + 30 + 40, GetFileSize(file_path()));
283 EXPECT_EQ(kInitialFileSize
+ 10 + 20 + 30 + 40 + 5,
284 fake_backend()->on_memory_usage());
285 EXPECT_EQ(kInitialFileSize
+ 20 + 30 + 40, fake_backend()->on_disk_usage());
289 EXPECT_EQ(kInitialFileSize
+ 20 + 30 + 40, fake_backend()->on_disk_usage());
292 TEST_F(QuotaReservationManagerTest
, MultipleClient
) {
293 scoped_refptr
<QuotaReservation
> reservation1
=
294 reservation_manager()->CreateReservation(GURL(kOrigin
), kType
);
295 RefreshReservation(reservation1
.get(), 10);
296 int64 cached_reserved_quota1
= reservation1
->remaining_quota();
298 scoped_refptr
<QuotaReservation
> reservation2
=
299 reservation_manager()->CreateReservation(GURL(kOrigin
), kType
);
300 RefreshReservation(reservation2
.get(), 20);
301 int64 cached_reserved_quota2
= reservation2
->remaining_quota();
303 scoped_ptr
<FakeWriter
> writer1(
304 new FakeWriter(reservation1
->GetOpenFileHandle(file_path())));
306 scoped_ptr
<FakeWriter
> writer2(
307 new FakeWriter(reservation2
->GetOpenFileHandle(file_path())));
309 cached_reserved_quota1
-= writer1
->Write(kInitialFileSize
+ 10);
310 EXPECT_LE(0, cached_reserved_quota1
);
312 cached_reserved_quota2
-= writer2
->Append(20);
313 EXPECT_LE(0, cached_reserved_quota2
);
315 writer1
->ReportUsage();
316 RefreshReservation(reservation1
.get(), 2);
317 cached_reserved_quota1
= reservation1
->remaining_quota();
319 writer2
->ReportUsage();
320 RefreshReservation(reservation2
.get(), 3);
321 cached_reserved_quota2
= reservation2
->remaining_quota();
326 EXPECT_EQ(kInitialFileSize
+ 10 + 20, GetFileSize(file_path()));
327 EXPECT_EQ(kInitialFileSize
+ 10 + 20 + 2 + 3,
328 fake_backend()->on_memory_usage());
329 EXPECT_EQ(kInitialFileSize
+ 10 + 20, fake_backend()->on_disk_usage());
332 EXPECT_EQ(kInitialFileSize
+ 10 + 20 + 3, fake_backend()->on_memory_usage());
335 EXPECT_EQ(kInitialFileSize
+ 10 + 20, fake_backend()->on_memory_usage());
338 TEST_F(QuotaReservationManagerTest
, ClientCrash
) {
339 scoped_refptr
<QuotaReservation
> reservation1
=
340 reservation_manager()->CreateReservation(GURL(kOrigin
), kType
);
341 RefreshReservation(reservation1
.get(), 15);
343 scoped_refptr
<QuotaReservation
> reservation2
=
344 reservation_manager()->CreateReservation(GURL(kOrigin
), kType
);
345 RefreshReservation(reservation2
.get(), 20);
348 FakeWriter
writer(reservation1
->GetOpenFileHandle(file_path()));
350 writer
.Write(kInitialFileSize
+ 10);
352 reservation1
->OnClientCrash();
353 writer
.ClearWithoutUsageReport();
357 EXPECT_EQ(kInitialFileSize
+ 10, GetFileSize(file_path()));
358 EXPECT_EQ(kInitialFileSize
+ 15 + 20, fake_backend()->on_memory_usage());
359 EXPECT_EQ(kInitialFileSize
+ 10, fake_backend()->on_disk_usage());
362 EXPECT_EQ(kInitialFileSize
+ 10, fake_backend()->on_memory_usage());
365 } // namespace content