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.
5 #include "content/browser/renderer_host/pepper/quota_reservation.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/quota_reservation.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using storage::QuotaReservationManager
;
25 const char kOrigin
[] = "http://example.com";
26 const storage::FileSystemType kType
= storage::kFileSystemTypeTemporary
;
28 const base::FilePath::StringType file1_name
= FILE_PATH_LITERAL("file1");
29 const base::FilePath::StringType file2_name
= FILE_PATH_LITERAL("file2");
30 const base::FilePath::StringType file3_name
= FILE_PATH_LITERAL("file3");
31 const int kFile1ID
= 1;
32 const int kFile2ID
= 2;
33 const int kFile3ID
= 3;
35 class FakeBackend
: public QuotaReservationManager::QuotaBackend
{
38 ~FakeBackend() override
{}
42 storage::FileSystemType type
,
44 const QuotaReservationManager::ReserveQuotaCallback
& callback
) override
{
45 base::ThreadTaskRunnerHandle::Get()->PostTask(
47 base::Bind(base::IgnoreResult(callback
), base::File::FILE_OK
, delta
));
50 void ReleaseReservedQuota(const GURL
& origin
,
51 storage::FileSystemType type
,
52 int64 size
) override
{}
54 void CommitQuotaUsage(const GURL
& origin
,
55 storage::FileSystemType type
,
56 int64 delta
) override
{}
58 void IncrementDirtyCount(const GURL
& origin
,
59 storage::FileSystemType type
) override
{}
60 void DecrementDirtyCount(const GURL
& origin
,
61 storage::FileSystemType type
) override
{}
64 DISALLOW_COPY_AND_ASSIGN(FakeBackend
);
69 class QuotaReservationTest
: public testing::Test
{
71 QuotaReservationTest() {}
72 ~QuotaReservationTest() override
{}
74 void SetUp() override
{
75 ASSERT_TRUE(work_dir_
.CreateUniqueTempDir());
77 reservation_manager_
.reset(new QuotaReservationManager(
78 scoped_ptr
<QuotaReservationManager::QuotaBackend
>(new FakeBackend
)));
81 void TearDown() override
{
82 reservation_manager_
.reset();
83 base::RunLoop().RunUntilIdle();
86 base::FilePath
MakeFilePath(const base::FilePath::StringType
& file_name
) {
87 return work_dir_
.path().Append(file_name
);
90 storage::FileSystemURL
MakeFileSystemURL(
91 const base::FilePath::StringType
& file_name
) {
92 return storage::FileSystemURL::CreateForTest(
93 GURL(kOrigin
), kType
, MakeFilePath(file_name
));
96 scoped_refptr
<QuotaReservation
> CreateQuotaReservation(
97 scoped_refptr
<storage::QuotaReservation
> reservation
,
99 storage::FileSystemType type
) {
100 // Sets reservation_ as a side effect.
101 return scoped_refptr
<QuotaReservation
>(
102 new QuotaReservation(reservation
, origin
, type
));
105 void SetFileSize(const base::FilePath::StringType
& file_name
, int64 size
) {
106 base::File
file(MakeFilePath(file_name
),
107 base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_WRITE
);
108 ASSERT_TRUE(file
.IsValid());
109 ASSERT_TRUE(file
.SetLength(size
));
112 QuotaReservationManager
* reservation_manager() {
113 return reservation_manager_
.get();
117 base::MessageLoop message_loop_
;
118 base::ScopedTempDir work_dir_
;
119 scoped_ptr
<storage::QuotaReservationManager
> reservation_manager_
;
121 DISALLOW_COPY_AND_ASSIGN(QuotaReservationTest
);
124 void GotReservedQuota(int64
* reserved_quota_ptr
,
125 ppapi::FileGrowthMap
* file_growths_ptr
,
126 int64 reserved_quota
,
127 const ppapi::FileSizeMap
& maximum_written_offsets
) {
128 *reserved_quota_ptr
= reserved_quota
;
130 file_growths_ptr
->clear();
131 for (ppapi::FileSizeMap::const_iterator it
= maximum_written_offsets
.begin();
132 it
!= maximum_written_offsets
.end();
134 (*file_growths_ptr
)[it
->first
] = ppapi::FileGrowth(it
->second
, 0);
137 void ReserveQuota(scoped_refptr
<QuotaReservation
> quota_reservation
,
139 int64
* reserved_quota
,
140 ppapi::FileGrowthMap
* file_growths
) {
141 quota_reservation
->ReserveQuota(
144 base::Bind(&GotReservedQuota
, reserved_quota
, file_growths
));
145 base::RunLoop().RunUntilIdle();
149 // 1) We can reserve quota with no files open.
150 // 2) Open a file, grow it, close it, and reserve quota with correct sizes.
151 TEST_F(QuotaReservationTest
, ReserveQuota
) {
152 GURL
origin(kOrigin
);
153 storage::FileSystemType type
= kType
;
155 scoped_refptr
<storage::QuotaReservation
> reservation(
156 reservation_manager()->CreateReservation(origin
, type
));
157 scoped_refptr
<QuotaReservation
> test
=
158 CreateQuotaReservation(reservation
, origin
, type
);
160 // Reserve quota with no files open.
162 int64 reserved_quota
;
163 ppapi::FileGrowthMap file_growths
;
164 ReserveQuota(test
, amount
, &reserved_quota
, &file_growths
);
165 EXPECT_EQ(amount
, reserved_quota
);
166 EXPECT_EQ(0U, file_growths
.size());
168 // Open a file, refresh the reservation, extend the file, and close it.
169 int64 file_size
= 10;
170 SetFileSize(file1_name
, file_size
);
171 int64 open_file_size
=
172 test
->OpenFile(kFile1ID
, MakeFileSystemURL(file1_name
));
173 EXPECT_EQ(file_size
, open_file_size
);
175 file_growths
[kFile1ID
] = ppapi::FileGrowth(file_size
, 0); // 1 file open.
176 ReserveQuota(test
, amount
, &reserved_quota
, &file_growths
);
177 EXPECT_EQ(amount
, reserved_quota
);
178 EXPECT_EQ(1U, file_growths
.size());
179 EXPECT_EQ(file_size
, file_growths
[kFile1ID
].max_written_offset
);
181 int64 new_file_size
= 30;
182 SetFileSize(file1_name
, new_file_size
);
184 EXPECT_EQ(amount
, reservation
->remaining_quota());
185 test
->CloseFile(kFile1ID
, ppapi::FileGrowth(new_file_size
, 0));
186 EXPECT_EQ(amount
- (new_file_size
- file_size
),
187 reservation
->remaining_quota());
191 // 1) We can open and close multiple files.
192 TEST_F(QuotaReservationTest
, MultipleFiles
) {
193 GURL
origin(kOrigin
);
194 storage::FileSystemType type
= kType
;
196 scoped_refptr
<storage::QuotaReservation
> reservation(
197 reservation_manager()->CreateReservation(origin
, type
));
198 scoped_refptr
<QuotaReservation
> test
=
199 CreateQuotaReservation(reservation
, origin
, type
);
201 // Open some files of different sizes.
202 int64 file1_size
= 10;
203 SetFileSize(file1_name
, file1_size
);
204 int64 open_file1_size
=
205 test
->OpenFile(kFile1ID
, MakeFileSystemURL(file1_name
));
206 EXPECT_EQ(file1_size
, open_file1_size
);
207 int64 file2_size
= 20;
208 SetFileSize(file2_name
, file2_size
);
209 int64 open_file2_size
=
210 test
->OpenFile(kFile2ID
, MakeFileSystemURL(file2_name
));
211 EXPECT_EQ(file2_size
, open_file2_size
);
212 int64 file3_size
= 30;
213 SetFileSize(file3_name
, file3_size
);
214 int64 open_file3_size
=
215 test
->OpenFile(kFile3ID
, MakeFileSystemURL(file3_name
));
216 EXPECT_EQ(file3_size
, open_file3_size
);
220 int64 reserved_quota
;
221 ppapi::FileGrowthMap file_growths
;
222 file_growths
[kFile1ID
] = ppapi::FileGrowth(file1_size
, 0); // 3 files open.
223 file_growths
[kFile2ID
] = ppapi::FileGrowth(file2_size
, 0);
224 file_growths
[kFile3ID
] = ppapi::FileGrowth(file3_size
, 0);
226 ReserveQuota(test
, amount
, &reserved_quota
, &file_growths
);
227 EXPECT_EQ(amount
, reserved_quota
);
228 EXPECT_EQ(3U, file_growths
.size());
229 EXPECT_EQ(file1_size
, file_growths
[kFile1ID
].max_written_offset
);
230 EXPECT_EQ(file2_size
, file_growths
[kFile2ID
].max_written_offset
);
231 EXPECT_EQ(file3_size
, file_growths
[kFile3ID
].max_written_offset
);
233 test
->CloseFile(kFile2ID
, ppapi::FileGrowth(file2_size
, 0));
235 file_growths
.erase(kFile2ID
);
236 ReserveQuota(test
, amount
, &reserved_quota
, &file_growths
);
237 EXPECT_EQ(amount
, reserved_quota
);
238 EXPECT_EQ(2U, file_growths
.size());
239 EXPECT_EQ(file1_size
, file_growths
[kFile1ID
].max_written_offset
);
240 EXPECT_EQ(file3_size
, file_growths
[kFile3ID
].max_written_offset
);
242 test
->CloseFile(kFile1ID
, ppapi::FileGrowth(file1_size
, 0));
243 test
->CloseFile(kFile3ID
, ppapi::FileGrowth(file3_size
, 0));
246 } // namespace content