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/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/quota_reservation.h"
17 using fileapi::FileSystemType
;
18 using fileapi::QuotaReservationManager
;
24 const char kOrigin
[] = "http://example.com";
25 const FileSystemType kType
= fileapi::kFileSystemTypeTemporary
;
27 const base::FilePath::StringType file1_name
= FILE_PATH_LITERAL("file1");
28 const base::FilePath::StringType file2_name
= FILE_PATH_LITERAL("file2");
29 const base::FilePath::StringType file3_name
= FILE_PATH_LITERAL("file3");
30 const int kFile1ID
= 1;
31 const int kFile2ID
= 2;
32 const int kFile3ID
= 3;
34 class FakeBackend
: public QuotaReservationManager::QuotaBackend
{
37 virtual ~FakeBackend() {}
39 virtual void ReserveQuota(
43 const QuotaReservationManager::ReserveQuotaCallback
& callback
) OVERRIDE
{
44 base::MessageLoopProxy::current()->PostTask(
46 base::Bind(base::IgnoreResult(callback
), base::File::FILE_OK
, delta
));
49 virtual void ReleaseReservedQuota(const GURL
& origin
,
51 int64 size
) OVERRIDE
{
54 virtual void CommitQuotaUsage(const GURL
& origin
,
56 int64 delta
) OVERRIDE
{
59 virtual void IncrementDirtyCount(const GURL
& origin
,
60 FileSystemType type
) OVERRIDE
{}
61 virtual void DecrementDirtyCount(const GURL
& origin
,
62 FileSystemType type
) OVERRIDE
{}
65 DISALLOW_COPY_AND_ASSIGN(FakeBackend
);
70 class QuotaReservationTest
: public testing::Test
{
72 QuotaReservationTest() {}
73 virtual ~QuotaReservationTest() {}
75 virtual void SetUp() OVERRIDE
{
76 ASSERT_TRUE(work_dir_
.CreateUniqueTempDir());
78 reservation_manager_
.reset(new QuotaReservationManager(
79 scoped_ptr
<QuotaReservationManager::QuotaBackend
>(new FakeBackend
)));
82 virtual void TearDown() OVERRIDE
{
83 reservation_manager_
.reset();
84 base::RunLoop().RunUntilIdle();
87 base::FilePath
MakeFilePath(const base::FilePath::StringType
& file_name
) {
88 return work_dir_
.path().Append(file_name
);
91 fileapi::FileSystemURL
MakeFileSystemURL(
92 const base::FilePath::StringType
& file_name
) {
93 return fileapi::FileSystemURL::CreateForTest(
94 GURL(kOrigin
), kType
, MakeFilePath(file_name
));
97 scoped_refptr
<QuotaReservation
> CreateQuotaReservation(
98 scoped_refptr
<fileapi::QuotaReservation
> reservation
,
100 FileSystemType type
) {
101 // Sets reservation_ as a side effect.
102 return scoped_refptr
<QuotaReservation
>(
103 new QuotaReservation(reservation
, origin
, type
));
106 void SetFileSize(const base::FilePath::StringType
& file_name
, int64 size
) {
107 base::File
file(MakeFilePath(file_name
),
108 base::File::FLAG_OPEN_ALWAYS
| base::File::FLAG_WRITE
);
109 ASSERT_TRUE(file
.IsValid());
110 ASSERT_TRUE(file
.SetLength(size
));
113 QuotaReservationManager
* reservation_manager() {
114 return reservation_manager_
.get();
118 base::MessageLoop message_loop_
;
119 base::ScopedTempDir work_dir_
;
120 scoped_ptr
<fileapi::QuotaReservationManager
> reservation_manager_
;
122 DISALLOW_COPY_AND_ASSIGN(QuotaReservationTest
);
125 void GotReservedQuota(
126 int64
* reserved_quota_ptr
,
127 ppapi::FileGrowthMap
* file_growths_ptr
,
128 int64 reserved_quota
,
129 const ppapi::FileSizeMap
& maximum_written_offsets
) {
130 *reserved_quota_ptr
= reserved_quota
;
132 file_growths_ptr
->clear();
133 for (ppapi::FileSizeMap::const_iterator it
= maximum_written_offsets
.begin();
134 it
!= maximum_written_offsets
.end(); ++it
)
135 (*file_growths_ptr
)[it
->first
] = ppapi::FileGrowth(it
->second
, 0);
139 scoped_refptr
<QuotaReservation
> quota_reservation
,
141 int64
* reserved_quota
,
142 ppapi::FileGrowthMap
* file_growths
) {
143 quota_reservation
->ReserveQuota(amount
,
145 base::Bind(&GotReservedQuota
,
148 base::RunLoop().RunUntilIdle();
152 // 1) We can reserve quota with no files open.
153 // 2) Open a file, grow it, close it, and reserve quota with correct sizes.
154 TEST_F(QuotaReservationTest
, ReserveQuota
) {
155 GURL
origin(kOrigin
);
156 FileSystemType type
= kType
;
158 scoped_refptr
<fileapi::QuotaReservation
> reservation(
159 reservation_manager()->CreateReservation(origin
, type
));
160 scoped_refptr
<QuotaReservation
> test
=
161 CreateQuotaReservation(reservation
, origin
, type
);
163 // Reserve quota with no files open.
165 int64 reserved_quota
;
166 ppapi::FileGrowthMap file_growths
;
167 ReserveQuota(test
, amount
, &reserved_quota
, &file_growths
);
168 EXPECT_EQ(amount
, reserved_quota
);
169 EXPECT_EQ(0U, file_growths
.size());
171 // Open a file, refresh the reservation, extend the file, and close it.
172 int64 file_size
= 10;
173 SetFileSize(file1_name
, file_size
);
174 int64 open_file_size
= test
->OpenFile(kFile1ID
,
175 MakeFileSystemURL(file1_name
));
176 EXPECT_EQ(file_size
, open_file_size
);
178 file_growths
[kFile1ID
] = ppapi::FileGrowth(file_size
, 0); // 1 file open.
179 ReserveQuota(test
, amount
, &reserved_quota
, &file_growths
);
180 EXPECT_EQ(amount
, reserved_quota
);
181 EXPECT_EQ(1U, file_growths
.size());
182 EXPECT_EQ(file_size
, file_growths
[kFile1ID
].max_written_offset
);
184 int64 new_file_size
= 30;
185 SetFileSize(file1_name
, new_file_size
);
187 EXPECT_EQ(amount
, reservation
->remaining_quota());
188 test
->CloseFile(kFile1ID
, ppapi::FileGrowth(new_file_size
, 0));
189 EXPECT_EQ(amount
- (new_file_size
- file_size
),
190 reservation
->remaining_quota());
194 // 1) We can open and close multiple files.
195 TEST_F(QuotaReservationTest
, MultipleFiles
) {
196 GURL
origin(kOrigin
);
197 FileSystemType type
= kType
;
199 scoped_refptr
<fileapi::QuotaReservation
> reservation(
200 reservation_manager()->CreateReservation(origin
, type
));
201 scoped_refptr
<QuotaReservation
> test
=
202 CreateQuotaReservation(reservation
, origin
, type
);
204 // Open some files of different sizes.
205 int64 file1_size
= 10;
206 SetFileSize(file1_name
, file1_size
);
207 int64 open_file1_size
= test
->OpenFile(kFile1ID
,
208 MakeFileSystemURL(file1_name
));
209 EXPECT_EQ(file1_size
, open_file1_size
);
210 int64 file2_size
= 20;
211 SetFileSize(file2_name
, file2_size
);
212 int64 open_file2_size
= test
->OpenFile(kFile2ID
,
213 MakeFileSystemURL(file2_name
));
214 EXPECT_EQ(file2_size
, open_file2_size
);
215 int64 file3_size
= 30;
216 SetFileSize(file3_name
, file3_size
);
217 int64 open_file3_size
= test
->OpenFile(kFile3ID
,
218 MakeFileSystemURL(file3_name
));
219 EXPECT_EQ(file3_size
, open_file3_size
);
223 int64 reserved_quota
;
224 ppapi::FileGrowthMap file_growths
;
225 file_growths
[kFile1ID
] = ppapi::FileGrowth(file1_size
, 0); // 3 files open.
226 file_growths
[kFile2ID
] = ppapi::FileGrowth(file2_size
, 0);
227 file_growths
[kFile3ID
] = ppapi::FileGrowth(file3_size
, 0);
229 ReserveQuota(test
, amount
, &reserved_quota
, &file_growths
);
230 EXPECT_EQ(amount
, reserved_quota
);
231 EXPECT_EQ(3U, file_growths
.size());
232 EXPECT_EQ(file1_size
, file_growths
[kFile1ID
].max_written_offset
);
233 EXPECT_EQ(file2_size
, file_growths
[kFile2ID
].max_written_offset
);
234 EXPECT_EQ(file3_size
, file_growths
[kFile3ID
].max_written_offset
);
236 test
->CloseFile(kFile2ID
, ppapi::FileGrowth(file2_size
, 0));
238 file_growths
.erase(kFile2ID
);
239 ReserveQuota(test
, amount
, &reserved_quota
, &file_growths
);
240 EXPECT_EQ(amount
, reserved_quota
);
241 EXPECT_EQ(2U, file_growths
.size());
242 EXPECT_EQ(file1_size
, file_growths
[kFile1ID
].max_written_offset
);
243 EXPECT_EQ(file3_size
, file_growths
[kFile3ID
].max_written_offset
);
245 test
->CloseFile(kFile1ID
, ppapi::FileGrowth(file1_size
, 0));
246 test
->CloseFile(kFile3ID
, ppapi::FileGrowth(file3_size
, 0));
249 } // namespace content