1 // Copyright (c) 2011 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.
9 #include "base/basictypes.h"
10 #include "base/bind.h"
11 #include "base/file_util.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/platform_file.h"
16 #include "content/renderer/pepper/quota_file_io.h"
17 #include "content/test/ppapi_unittest.h"
19 using base::MessageLoopProxy
;
20 using base::PlatformFile
;
21 using base::PlatformFileError
;
26 class QuotaMockDelegate
: public QuotaFileIO::Delegate
{
28 typedef QuotaFileIO::Delegate::AvailableSpaceCallback Callback
;
31 : available_space_(0),
32 will_update_count_(0),
33 file_thread_(MessageLoopProxy::current()),
36 virtual ~QuotaMockDelegate() {}
38 virtual void QueryAvailableSpace(
40 quota::StorageType type
,
41 const Callback
& callback
) OVERRIDE
{
42 DCHECK_EQ(false, callback
.is_null());
43 MessageLoopProxy::current()->PostTask(
44 FROM_HERE
, base::Bind(
45 &QuotaMockDelegate::RunAvailableSpaceCallback
,
46 weak_factory_
.GetWeakPtr(), callback
));
49 virtual void WillUpdateFile(const GURL
& file_path
) OVERRIDE
{
50 file_path_
= file_path
;
54 virtual void DidUpdateFile(const GURL
& file_path
, int64_t delta
) OVERRIDE
{
55 ASSERT_EQ(file_path_
, file_path
);
56 ASSERT_GT(will_update_count_
, 0);
58 available_space_
-= delta
;
61 virtual scoped_refptr
<base::MessageLoopProxy
>
62 GetFileThreadMessageLoopProxy() OVERRIDE
{
66 void set_available_space(int64 available
) { available_space_
= available
; }
67 int64_t available_space() const { return available_space_
; }
70 void RunAvailableSpaceCallback(const Callback
& callback
) {
71 callback
.Run(available_space_
);
74 int64_t available_space_
;
75 int will_update_count_
;
77 scoped_refptr
<MessageLoopProxy
> file_thread_
;
78 base::WeakPtrFactory
<QuotaMockDelegate
> weak_factory_
;
82 class QuotaFileIOTest
: public PpapiUnittest
{
86 weak_factory_(this) {}
88 virtual void SetUp() OVERRIDE
{
89 PpapiUnittest::SetUp();
90 ASSERT_TRUE(dir_
.CreateUniqueTempDir());
92 ASSERT_TRUE(file_util::CreateTemporaryFileInDir(dir_
.path(), &path
));
93 int file_flags
= base::PLATFORM_FILE_OPEN
|
94 base::PLATFORM_FILE_READ
|
95 base::PLATFORM_FILE_WRITE
|
96 base::PLATFORM_FILE_WRITE_ATTRIBUTES
;
98 file_
= base::kInvalidPlatformFileValue
;
99 PlatformFileError error
= base::PLATFORM_FILE_OK
;
100 file_
= base::CreatePlatformFile(path
, file_flags
, &created
, &error
);
101 ASSERT_EQ(base::PLATFORM_FILE_OK
, error
);
102 ASSERT_NE(base::kInvalidPlatformFileValue
, file_
);
103 ASSERT_FALSE(created
);
104 delegate_
= new QuotaMockDelegate
; // Owned by QuotaFileIO.
105 quota_file_io_
.reset(new QuotaFileIO(
106 delegate_
, file_
, GURL(), PP_FILESYSTEMTYPE_LOCALTEMPORARY
));
109 virtual void TearDown() OVERRIDE
{
110 quota_file_io_
.reset();
111 if (file_
!= base::kInvalidPlatformFileValue
)
112 base::ClosePlatformFile(file_
);
113 PpapiUnittest::TearDown();
117 void WriteTestBody() {
118 // Attempt to write zero bytes.
119 EXPECT_FALSE(quota_file_io_
->Write(
121 base::Bind(&QuotaFileIOTest::DidWrite
, weak_factory_
.GetWeakPtr())));
122 // Attempt to write negative number of bytes.
123 EXPECT_FALSE(quota_file_io_
->Write(
124 0, "data", std::numeric_limits
<int32_t>::min(),
125 base::Bind(&QuotaFileIOTest::DidWrite
, weak_factory_
.GetWeakPtr())));
127 delegate()->set_available_space(100);
128 std::string read_buffer
;
130 // Write 8 bytes at offset 0 (-> length=8).
131 std::string
data("12345678");
133 base::MessageLoop::current()->RunUntilIdle();
134 ASSERT_EQ(1U, num_results());
135 EXPECT_EQ(static_cast<int>(data
.size()), bytes_written().front());
136 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
137 EXPECT_EQ(100 - 8, delegate()->available_space());
140 EXPECT_EQ(8, GetPlatformFileSize());
141 ReadPlatformFile(&read_buffer
);
142 EXPECT_EQ(data
, read_buffer
);
144 // Write 5 bytes at offset 5 (-> length=10).
147 base::MessageLoop::current()->RunUntilIdle();
148 ASSERT_EQ(1U, num_results());
149 EXPECT_EQ(static_cast<int>(data
.size()), bytes_written().front());
150 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
151 EXPECT_EQ(100 - 10, delegate()->available_space());
154 EXPECT_EQ(10, GetPlatformFileSize());
155 ReadPlatformFile(&read_buffer
);
156 EXPECT_EQ("1234555555", read_buffer
);
158 // Write 7 bytes at offset 8 (-> length=15).
161 base::MessageLoop::current()->RunUntilIdle();
162 ASSERT_EQ(1U, num_results());
163 EXPECT_EQ(static_cast<int>(data
.size()), bytes_written().front());
164 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
165 EXPECT_EQ(100 - 15, delegate()->available_space());
168 EXPECT_EQ(15, GetPlatformFileSize());
169 ReadPlatformFile(&read_buffer
);
170 EXPECT_EQ("123455559012345", read_buffer
);
172 // Write 2 bytes at offset 2 (-> length=15).
175 base::MessageLoop::current()->RunUntilIdle();
176 ASSERT_EQ(1U, num_results());
177 EXPECT_EQ(static_cast<int>(data
.size()), bytes_written().front());
178 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
179 EXPECT_EQ(100 - 15, delegate()->available_space());
182 EXPECT_EQ(15, GetPlatformFileSize());
183 ReadPlatformFile(&read_buffer
);
184 EXPECT_EQ("123355559012345", read_buffer
);
186 // Write 4 bytes at offset 20 (-> length=24).
189 base::MessageLoop::current()->RunUntilIdle();
190 ASSERT_EQ(1U, num_results());
191 EXPECT_EQ(static_cast<int>(data
.size()), bytes_written().front());
192 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
193 EXPECT_EQ(100 - 24, delegate()->available_space());
196 EXPECT_EQ(24, GetPlatformFileSize());
197 ReadPlatformFile(&read_buffer
);
198 EXPECT_EQ(std::string("123355559012345\0\0\0\0\0XXXX", 24), read_buffer
);
200 delegate()->set_available_space(5);
202 // Quota error case. Write 7 bytes at offset 23 (-> length is unchanged)
205 base::MessageLoop::current()->RunUntilIdle();
206 ASSERT_EQ(1U, num_results());
207 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE
, status().front());
208 EXPECT_EQ(5, delegate()->available_space());
211 // Overlapping write. Write 6 bytes at offset 2 (-> length is unchanged)
214 base::MessageLoop::current()->RunUntilIdle();
215 ASSERT_EQ(1U, num_results());
216 EXPECT_EQ(static_cast<int>(data
.size()), bytes_written().front());
217 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
218 EXPECT_EQ(5, delegate()->available_space());
221 // Overlapping + extending the file size, but within the quota.
222 // Write 6 bytes at offset 23 (-> length=29).
224 base::MessageLoop::current()->RunUntilIdle();
225 ASSERT_EQ(1U, num_results());
226 EXPECT_EQ(static_cast<int>(data
.size()), bytes_written().front());
227 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
228 EXPECT_EQ(0, delegate()->available_space());
231 EXPECT_EQ(29, GetPlatformFileSize());
232 ReadPlatformFile(&read_buffer
);
233 EXPECT_EQ(std::string("12ABCDEF9012345\0\0\0\0\0XXXABCDEF", 29),
237 void SetLengthTestBody() {
238 delegate()->set_available_space(100);
241 base::MessageLoop::current()->RunUntilIdle();
242 ASSERT_EQ(1U, num_results());
243 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
244 EXPECT_EQ(0, GetPlatformFileSize());
245 EXPECT_EQ(100, delegate()->available_space());
249 base::MessageLoop::current()->RunUntilIdle();
250 ASSERT_EQ(1U, num_results());
251 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
252 EXPECT_EQ(100 - 8, delegate()->available_space());
255 EXPECT_EQ(8, GetPlatformFileSize());
258 base::MessageLoop::current()->RunUntilIdle();
259 ASSERT_EQ(1U, num_results());
260 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
261 EXPECT_EQ(100 - 16, delegate()->available_space());
264 EXPECT_EQ(16, GetPlatformFileSize());
267 base::MessageLoop::current()->RunUntilIdle();
268 ASSERT_EQ(1U, num_results());
269 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
270 EXPECT_EQ(100 - 4, delegate()->available_space());
273 EXPECT_EQ(4, GetPlatformFileSize());
276 base::MessageLoop::current()->RunUntilIdle();
277 ASSERT_EQ(1U, num_results());
278 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
279 EXPECT_EQ(100, delegate()->available_space());
282 EXPECT_EQ(0, GetPlatformFileSize());
284 delegate()->set_available_space(5);
288 base::MessageLoop::current()->RunUntilIdle();
289 ASSERT_EQ(1U, num_results());
290 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE
, status().front());
291 EXPECT_EQ(5, delegate()->available_space());
295 QuotaMockDelegate
* delegate() {
299 void Write(int64_t offset
, const std::string
& data
) {
300 ASSERT_TRUE(quota_file_io_
->Write(
301 offset
, data
.c_str(), data
.size(),
302 base::Bind(&QuotaFileIOTest::DidWrite
, weak_factory_
.GetWeakPtr())));
305 void SetLength(int64_t length
) {
306 ASSERT_TRUE(quota_file_io_
->SetLength(
308 base::Bind(&QuotaFileIOTest::DidSetLength
,
309 weak_factory_
.GetWeakPtr())));
312 void DidWrite(PlatformFileError status
, int bytes_written
) {
313 status_
.push_back(status
);
314 bytes_written_
.push_back(bytes_written
);
317 void DidSetLength(PlatformFileError status
) {
318 status_
.push_back(status
);
321 size_t num_results() const { return status_
.size(); }
322 const std::deque
<int>& bytes_written() const { return bytes_written_
; }
323 const std::deque
<PlatformFileError
>& status() const { return status_
; }
325 void reset_results() {
326 bytes_written_
.clear();
331 bytes_written_
.pop_front();
335 void ReadPlatformFile(std::string
* data
) {
338 int32_t read_offset
= 0;
340 int rv
= base::ReadPlatformFile(file_
, read_offset
, buf
, sizeof(buf
));
345 data
->append(buf
, rv
);
349 int64_t GetPlatformFileSize() {
350 base::PlatformFileInfo info
;
351 EXPECT_TRUE(base::GetPlatformFileInfo(file_
, &info
));
355 void SetPlatformFileSize(int64_t length
) {
356 EXPECT_TRUE(base::TruncatePlatformFile(file_
, length
));
360 base::ScopedTempDir dir_
;
362 scoped_ptr
<QuotaFileIO
> quota_file_io_
;
363 std::deque
<int> bytes_written_
;
364 std::deque
<PlatformFileError
> status_
;
365 QuotaMockDelegate
* delegate_
;
366 base::WeakPtrFactory
<QuotaFileIOTest
> weak_factory_
;
369 TEST_F(QuotaFileIOTest
, Write
) {
373 TEST_F(QuotaFileIOTest
, SetLength
) {
377 TEST_F(QuotaFileIOTest
, ParallelWrites
) {
378 delegate()->set_available_space(22);
379 std::string read_buffer
;
381 const std::string data1
[] = {
382 std::string("12345678"),
383 std::string("55555"),
384 std::string("9012345"),
389 base::MessageLoop::current()->RunUntilIdle();
391 ASSERT_EQ(ARRAYSIZE_UNSAFE(data1
), num_results());
392 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(data1
); ++i
) {
393 EXPECT_EQ(static_cast<int>(data1
[i
].size()), bytes_written().front());
394 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
398 EXPECT_EQ(22 - 15, delegate()->available_space());
399 EXPECT_EQ(15, GetPlatformFileSize());
400 ReadPlatformFile(&read_buffer
);
401 EXPECT_EQ("123455559012345", read_buffer
);
403 // The second write will fail for quota error.
404 const std::string data2
[] = {
410 base::MessageLoop::current()->RunUntilIdle();
412 ASSERT_EQ(ARRAYSIZE_UNSAFE(data2
), num_results());
413 EXPECT_EQ(static_cast<int>(data2
[0].size()), bytes_written().front());
414 EXPECT_EQ(base::PLATFORM_FILE_OK
, status().front());
416 EXPECT_EQ(0, bytes_written().front());
417 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE
, status().front());
420 EXPECT_EQ(22 - 15, delegate()->available_space());
421 EXPECT_EQ(15, GetPlatformFileSize());
422 ReadPlatformFile(&read_buffer
);
423 EXPECT_EQ("123355559012345", read_buffer
);
426 } // namespace content