1 // Copyright (c) 2012 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 "ppapi/tests/test_file_io.h"
12 #include <sys/types.h>
16 #include "ppapi/c/dev/ppb_testing_dev.h"
17 #include "ppapi/c/pp_errors.h"
18 #include "ppapi/c/ppb_file_io.h"
19 #include "ppapi/c/private/pp_file_handle.h"
20 #include "ppapi/c/trusted/ppb_file_io_trusted.h"
21 #include "ppapi/cpp/file_io.h"
22 #include "ppapi/cpp/file_ref.h"
23 #include "ppapi/cpp/file_system.h"
24 #include "ppapi/cpp/instance.h"
25 #include "ppapi/cpp/module.h"
26 #include "ppapi/cpp/private/file_io_private.h"
27 #include "ppapi/cpp/private/pass_file_handle.h"
28 #include "ppapi/tests/test_utils.h"
29 #include "ppapi/tests/testing_instance.h"
31 #if defined(PPAPI_OS_WIN)
34 // TODO(hamaji): Use standard windows APIs instead of compatibility layer?
40 # include <sys/mman.h>
44 REGISTER_TEST_CASE(FileIO
);
48 std::string
ReportMismatch(const std::string
& method_name
,
49 const std::string
& returned_result
,
50 const std::string
& expected_result
) {
51 return method_name
+ " returned '" + returned_result
+ "'; '" +
52 expected_result
+ "' expected.";
55 std::string
ReportOpenError(int32_t open_flags
) {
56 static const char* kFlagNames
[] = {
57 "PP_FILEOPENFLAG_READ",
58 "PP_FILEOPENFLAG_WRITE",
59 "PP_FILEOPENFLAG_CREATE",
60 "PP_FILEOPENFLAG_TRUNCATE",
61 "PP_FILEOPENFLAG_EXCLUSIVE"
64 std::string result
= "FileIO:Open had unexpected behavior with flags: ";
65 bool first_flag
= true;
66 for (int32_t mask
= 1, index
= 0; mask
<= PP_FILEOPENFLAG_EXCLUSIVE
;
67 mask
<<= 1, ++index
) {
68 if (mask
& open_flags
) {
74 result
+= kFlagNames
[index
];
83 int32_t ReadEntireFile(PP_Instance instance
,
87 CallbackType callback_type
) {
88 TestCompletionCallback
callback(instance
, callback_type
);
90 int32_t read_offset
= offset
;
93 callback
.WaitForResult(
94 file_io
->Read(read_offset
, buf
, sizeof(buf
), callback
.GetCallback()));
95 if (callback
.result() < 0)
96 return callback
.result();
97 if (callback
.result() == 0)
99 read_offset
+= callback
.result();
100 data
->append(buf
, callback
.result());
106 int32_t ReadToArrayEntireFile(PP_Instance instance
,
110 CallbackType callback_type
) {
111 TestCompletionCallbackWithOutput
< std::vector
<char> > callback(
112 instance
, callback_type
);
115 callback
.WaitForResult(file_io
->Read(offset
, 256, callback
.GetCallback()));
116 int32_t rv
= callback
.result();
121 const std::vector
<char>& output
= callback
.output();
122 assert(rv
== static_cast<int32_t>(output
.size()));
124 data
->append(output
.begin(), output
.end());
130 bool ReadEntireFileFromFileHandle(int fd
, std::string
* data
) {
131 if (lseek(fd
, 0, SEEK_SET
) < 0)
138 ret
= read(fd
, buf
, sizeof(buf
));
140 data
->append(buf
, ret
);
145 int32_t WriteEntireBuffer(PP_Instance instance
,
148 const std::string
& data
,
149 CallbackType callback_type
) {
150 TestCompletionCallback
callback(instance
, callback_type
);
151 int32_t write_offset
= offset
;
152 const char* buf
= data
.c_str();
153 int32_t size
= data
.size();
155 while (write_offset
< offset
+ size
) {
156 callback
.WaitForResult(file_io
->Write(write_offset
,
157 &buf
[write_offset
- offset
],
158 size
- write_offset
+ offset
,
159 callback
.GetCallback()));
160 if (callback
.result() < 0)
161 return callback
.result();
162 if (callback
.result() == 0)
163 return PP_ERROR_FAILED
;
164 write_offset
+= callback
.result();
172 bool TestFileIO::Init() {
173 return CheckTestingInterface() && EnsureRunningOverHTTP();
176 void TestFileIO::RunTests(const std::string
& filter
) {
177 RUN_CALLBACK_TEST(TestFileIO
, Open
, filter
);
178 RUN_CALLBACK_TEST(TestFileIO
, OpenDirectory
, filter
);
179 RUN_CALLBACK_TEST(TestFileIO
, ReadWriteSetLength
, filter
);
180 RUN_CALLBACK_TEST(TestFileIO
, ReadToArrayWriteSetLength
, filter
);
181 RUN_CALLBACK_TEST(TestFileIO
, TouchQuery
, filter
);
182 RUN_CALLBACK_TEST(TestFileIO
, AbortCalls
, filter
);
183 RUN_CALLBACK_TEST(TestFileIO
, ParallelReads
, filter
);
184 RUN_CALLBACK_TEST(TestFileIO
, ParallelWrites
, filter
);
185 RUN_CALLBACK_TEST(TestFileIO
, NotAllowMixedReadWrite
, filter
);
186 RUN_CALLBACK_TEST(TestFileIO
, WillWriteWillSetLength
, filter
);
187 RUN_CALLBACK_TEST(TestFileIO
, RequestOSFileHandle
, filter
);
188 RUN_CALLBACK_TEST(TestFileIO
, RequestOSFileHandleWithOpenExclusive
, filter
);
189 RUN_CALLBACK_TEST(TestFileIO
, Mmap
, filter
);
191 // TODO(viettrungluu): add tests:
192 // - that PP_ERROR_PENDING is correctly returned
193 // - that operations respect the file open modes (flags)
196 std::string
TestFileIO::TestOpen() {
197 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
199 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
200 pp::FileRef
file_ref(file_system
, "/file_open");
202 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
203 CHECK_CALLBACK_BEHAVIOR(callback
);
204 ASSERT_EQ(PP_OK
, callback
.result());
207 result
= MatchOpenExpectations(
209 PP_FILEOPENFLAG_READ
,
210 DONT_CREATE_IF_DOESNT_EXIST
| OPEN_IF_EXISTS
| DONT_TRUNCATE_IF_EXISTS
);
214 // Test the behavior of the power set of
215 // { PP_FILEOPENFLAG_CREATE,
216 // PP_FILEOPENFLAG_TRUNCATE,
217 // PP_FILEOPENFLAG_EXCLUSIVE }.
219 // First of all, none of them are specified.
220 result
= MatchOpenExpectations(
222 PP_FILEOPENFLAG_WRITE
,
223 DONT_CREATE_IF_DOESNT_EXIST
| OPEN_IF_EXISTS
| DONT_TRUNCATE_IF_EXISTS
);
227 result
= MatchOpenExpectations(
229 PP_FILEOPENFLAG_WRITE
| PP_FILEOPENFLAG_CREATE
,
230 CREATE_IF_DOESNT_EXIST
| OPEN_IF_EXISTS
| DONT_TRUNCATE_IF_EXISTS
);
234 result
= MatchOpenExpectations(
236 PP_FILEOPENFLAG_WRITE
| PP_FILEOPENFLAG_EXCLUSIVE
,
237 DONT_CREATE_IF_DOESNT_EXIST
| OPEN_IF_EXISTS
| DONT_TRUNCATE_IF_EXISTS
);
241 result
= MatchOpenExpectations(
243 PP_FILEOPENFLAG_WRITE
| PP_FILEOPENFLAG_TRUNCATE
,
244 DONT_CREATE_IF_DOESNT_EXIST
| OPEN_IF_EXISTS
| TRUNCATE_IF_EXISTS
);
248 result
= MatchOpenExpectations(
250 PP_FILEOPENFLAG_WRITE
| PP_FILEOPENFLAG_CREATE
|
251 PP_FILEOPENFLAG_EXCLUSIVE
,
252 CREATE_IF_DOESNT_EXIST
| DONT_OPEN_IF_EXISTS
| DONT_TRUNCATE_IF_EXISTS
);
256 result
= MatchOpenExpectations(
258 PP_FILEOPENFLAG_WRITE
| PP_FILEOPENFLAG_CREATE
| PP_FILEOPENFLAG_TRUNCATE
,
259 CREATE_IF_DOESNT_EXIST
| OPEN_IF_EXISTS
| TRUNCATE_IF_EXISTS
);
263 result
= MatchOpenExpectations(
265 PP_FILEOPENFLAG_WRITE
| PP_FILEOPENFLAG_EXCLUSIVE
|
266 PP_FILEOPENFLAG_TRUNCATE
,
267 DONT_CREATE_IF_DOESNT_EXIST
| OPEN_IF_EXISTS
| TRUNCATE_IF_EXISTS
);
271 result
= MatchOpenExpectations(
273 PP_FILEOPENFLAG_WRITE
| PP_FILEOPENFLAG_CREATE
|
274 PP_FILEOPENFLAG_EXCLUSIVE
| PP_FILEOPENFLAG_TRUNCATE
,
275 CREATE_IF_DOESNT_EXIST
| DONT_OPEN_IF_EXISTS
| DONT_TRUNCATE_IF_EXISTS
);
279 // Invalid combination: PP_FILEOPENFLAG_TRUNCATE without
280 // PP_FILEOPENFLAG_WRITE.
281 result
= MatchOpenExpectations(
283 PP_FILEOPENFLAG_READ
| PP_FILEOPENFLAG_TRUNCATE
,
284 INVALID_FLAG_COMBINATION
);
291 std::string
TestFileIO::TestOpenDirectory() {
292 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
294 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
295 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
296 CHECK_CALLBACK_BEHAVIOR(callback
);
297 ASSERT_EQ(PP_OK
, callback
.result());
300 pp::FileRef
dir_ref(file_system
, "/test_dir_open_directory");
301 callback
.WaitForResult(dir_ref
.MakeDirectory(callback
.GetCallback()));
302 CHECK_CALLBACK_BEHAVIOR(callback
);
303 ASSERT_EQ(PP_OK
, callback
.result());
305 // Open the directory. This is expected to fail since directories cannot be
307 pp::FileIO
file_io(instance_
);
308 callback
.WaitForResult(file_io
.Open(dir_ref
, PP_FILEOPENFLAG_READ
,
309 callback
.GetCallback()));
310 CHECK_CALLBACK_BEHAVIOR(callback
);
311 ASSERT_EQ(PP_ERROR_NOTAFILE
, callback
.result());
316 std::string
TestFileIO::TestReadWriteSetLength() {
317 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
319 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
320 pp::FileRef
file_ref(file_system
, "/file_read_write_setlength");
321 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
322 CHECK_CALLBACK_BEHAVIOR(callback
);
323 ASSERT_EQ(PP_OK
, callback
.result());
325 pp::FileIO
file_io(instance_
);
326 callback
.WaitForResult(file_io
.Open(file_ref
,
327 PP_FILEOPENFLAG_CREATE
|
328 PP_FILEOPENFLAG_TRUNCATE
|
329 PP_FILEOPENFLAG_READ
|
330 PP_FILEOPENFLAG_WRITE
,
331 callback
.GetCallback()));
332 CHECK_CALLBACK_BEHAVIOR(callback
);
333 ASSERT_EQ(PP_OK
, callback
.result());
335 // Write something to the file.
336 int32_t rv
= WriteEntireBuffer(instance_
->pp_instance(), &file_io
, 0,
337 "test_test", callback_type());
338 ASSERT_EQ(PP_OK
, rv
);
340 // Attempt to read a negative number of bytes; it should fail.
342 callback
.WaitForResult(file_io
.Read(0,
345 callback
.GetCallback()));
346 CHECK_CALLBACK_BEHAVIOR(callback
);
347 ASSERT_EQ(PP_ERROR_FAILED
, callback
.result());
349 // Read the entire file.
350 std::string read_buffer
;
351 rv
= ReadEntireFile(instance_
->pp_instance(), &file_io
, 0, &read_buffer
,
353 ASSERT_EQ(PP_OK
, rv
);
354 ASSERT_EQ(std::string("test_test"), read_buffer
);
356 // Truncate the file.
357 callback
.WaitForResult(file_io
.SetLength(4, callback
.GetCallback()));
358 CHECK_CALLBACK_BEHAVIOR(callback
);
359 ASSERT_EQ(PP_OK
, callback
.result());
361 // Check the file contents.
363 rv
= ReadEntireFile(instance_
->pp_instance(), &file_io
, 0, &read_buffer
,
365 ASSERT_EQ(PP_OK
, rv
);
366 ASSERT_EQ(std::string("test"), read_buffer
);
368 // Try to read past the end of the file.
370 rv
= ReadEntireFile(instance_
->pp_instance(), &file_io
, 100, &read_buffer
,
372 ASSERT_EQ(PP_OK
, rv
);
373 ASSERT_TRUE(read_buffer
.empty());
375 // Write past the end of the file. The file should be zero-padded.
376 rv
= WriteEntireBuffer(instance_
->pp_instance(), &file_io
, 8, "test",
378 ASSERT_EQ(PP_OK
, rv
);
380 // Check the contents of the file.
382 rv
= ReadEntireFile(instance_
->pp_instance(), &file_io
, 0, &read_buffer
,
384 ASSERT_EQ(PP_OK
, rv
);
385 ASSERT_EQ(std::string("test\0\0\0\0test", 12), read_buffer
);
388 callback
.WaitForResult(file_io
.SetLength(16, callback
.GetCallback()));
389 CHECK_CALLBACK_BEHAVIOR(callback
);
390 ASSERT_EQ(PP_OK
, callback
.result());
392 // Check the contents of the file.
394 rv
= ReadEntireFile(instance_
->pp_instance(), &file_io
, 0, &read_buffer
,
396 ASSERT_EQ(PP_OK
, rv
);
397 ASSERT_EQ(std::string("test\0\0\0\0test\0\0\0\0", 16), read_buffer
);
399 // Write in the middle of the file.
400 rv
= WriteEntireBuffer(instance_
->pp_instance(), &file_io
, 4, "test",
402 ASSERT_EQ(PP_OK
, rv
);
404 // Check the contents of the file.
406 rv
= ReadEntireFile(instance_
->pp_instance(), &file_io
, 0, &read_buffer
,
408 ASSERT_EQ(PP_OK
, rv
);
409 ASSERT_EQ(std::string("testtesttest\0\0\0\0", 16), read_buffer
);
411 // Read from the middle of the file.
413 rv
= ReadEntireFile(instance_
->pp_instance(), &file_io
, 4, &read_buffer
,
415 ASSERT_EQ(PP_OK
, rv
);
416 ASSERT_EQ(std::string("testtest\0\0\0\0", 12), read_buffer
);
418 // Append to the end of the file.
419 pp::FileIO
file_io2(instance_
);
420 callback
.WaitForResult(file_io2
.Open(file_ref
,
421 PP_FILEOPENFLAG_CREATE
|
422 PP_FILEOPENFLAG_READ
|
423 PP_FILEOPENFLAG_APPEND
,
424 callback
.GetCallback()));
425 rv
= WriteEntireBuffer(instance_
->pp_instance(), &file_io2
, 0, "appended",
427 ASSERT_EQ(PP_OK
, rv
);
429 rv
= ReadEntireFile(instance_
->pp_instance(), &file_io2
, 0, &read_buffer
,
431 ASSERT_EQ(PP_OK
, rv
);
432 ASSERT_EQ(std::string("testtesttest\0\0\0\0appended", 24), read_buffer
);
437 // This is basically a copy of TestReadWriteSetLength, but with the new Read
438 // API. With this test case, we can make sure the two Read's have the same
440 std::string
TestFileIO::TestReadToArrayWriteSetLength() {
441 if (callback_type() == PP_BLOCKING
) {
442 // This test does not make sense for blocking callbacks.
445 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
447 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
448 pp::FileRef
file_ref(file_system
, "/file_read_write_setlength");
449 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
450 CHECK_CALLBACK_BEHAVIOR(callback
);
451 ASSERT_EQ(PP_OK
, callback
.result());
453 pp::FileIO
file_io(instance_
);
454 callback
.WaitForResult(file_io
.Open(file_ref
,
455 PP_FILEOPENFLAG_CREATE
|
456 PP_FILEOPENFLAG_TRUNCATE
|
457 PP_FILEOPENFLAG_READ
|
458 PP_FILEOPENFLAG_WRITE
,
459 callback
.GetCallback()));
460 CHECK_CALLBACK_BEHAVIOR(callback
);
461 ASSERT_EQ(PP_OK
, callback
.result());
463 // Write something to the file.
464 int32_t rv
= WriteEntireBuffer(instance_
->pp_instance(), &file_io
, 0,
465 "test_test", callback_type());
466 ASSERT_EQ(PP_OK
, rv
);
468 TestCompletionCallbackWithOutput
< std::vector
<char> > callback2(
469 instance_
->pp_instance(), callback_type());
470 // Attempt to read a negative number of bytes; it should fail.
471 callback2
.WaitForResult(file_io
.Read(0, -1, callback2
.GetCallback()));
472 CHECK_CALLBACK_BEHAVIOR(callback2
);
473 ASSERT_EQ(PP_ERROR_FAILED
, callback2
.result());
475 // Read the entire file.
476 std::string read_buffer
;
477 read_buffer
.reserve(10);
478 rv
= ReadToArrayEntireFile(instance_
->pp_instance(), &file_io
, 0,
479 &read_buffer
, callback_type());
480 ASSERT_EQ(PP_OK
, rv
);
481 ASSERT_EQ(std::string("test_test"), read_buffer
);
483 // Truncate the file.
484 callback
.WaitForResult(file_io
.SetLength(4, callback
.GetCallback()));
485 CHECK_CALLBACK_BEHAVIOR(callback
);
486 ASSERT_EQ(PP_OK
, rv
);
488 // Check the file contents.
490 rv
= ReadToArrayEntireFile(instance_
->pp_instance(), &file_io
, 0,
491 &read_buffer
, callback_type());
492 ASSERT_EQ(PP_OK
, rv
);
493 ASSERT_EQ(std::string("test"), read_buffer
);
495 // Try to read past the end of the file.
497 rv
= ReadToArrayEntireFile(instance_
->pp_instance(), &file_io
, 100,
498 &read_buffer
, callback_type());
499 ASSERT_EQ(PP_OK
, rv
);
500 ASSERT_TRUE(read_buffer
.empty());
502 // Write past the end of the file. The file should be zero-padded.
503 rv
= WriteEntireBuffer(instance_
->pp_instance(), &file_io
, 8, "test",
505 ASSERT_EQ(PP_OK
, rv
);
507 // Check the contents of the file.
509 rv
= ReadToArrayEntireFile(instance_
->pp_instance(), &file_io
, 0,
510 &read_buffer
, callback_type());
511 ASSERT_EQ(PP_OK
, rv
);
512 ASSERT_EQ(std::string("test\0\0\0\0test", 12), read_buffer
);
515 callback
.WaitForResult(file_io
.SetLength(16, callback
.GetCallback()));
516 CHECK_CALLBACK_BEHAVIOR(callback
);
517 ASSERT_EQ(PP_OK
, callback
.result());
519 // Check the contents of the file.
521 rv
= ReadToArrayEntireFile(instance_
->pp_instance(), &file_io
, 0,
522 &read_buffer
, callback_type());
523 ASSERT_EQ(PP_OK
, rv
);
524 ASSERT_EQ(std::string("test\0\0\0\0test\0\0\0\0", 16), read_buffer
);
526 // Write in the middle of the file.
527 rv
= WriteEntireBuffer(instance_
->pp_instance(), &file_io
, 4, "test",
529 ASSERT_EQ(PP_OK
, rv
);
531 // Check the contents of the file.
533 rv
= ReadToArrayEntireFile(instance_
->pp_instance(), &file_io
, 0,
534 &read_buffer
, callback_type());
535 ASSERT_EQ(PP_OK
, rv
);
536 ASSERT_EQ(std::string("testtesttest\0\0\0\0", 16), read_buffer
);
538 // Read from the middle of the file.
540 rv
= ReadToArrayEntireFile(instance_
->pp_instance(), &file_io
, 4,
541 &read_buffer
, callback_type());
542 ASSERT_EQ(PP_OK
, rv
);
543 ASSERT_EQ(std::string("testtest\0\0\0\0", 12), read_buffer
);
548 std::string
TestFileIO::TestTouchQuery() {
549 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
551 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
552 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
553 CHECK_CALLBACK_BEHAVIOR(callback
);
554 ASSERT_EQ(PP_OK
, callback
.result());
556 pp::FileRef
file_ref(file_system
, "/file_touch");
557 pp::FileIO
file_io(instance_
);
558 callback
.WaitForResult(file_io
.Open(file_ref
,
559 PP_FILEOPENFLAG_CREATE
|
560 PP_FILEOPENFLAG_TRUNCATE
|
561 PP_FILEOPENFLAG_WRITE
,
562 callback
.GetCallback()));
563 CHECK_CALLBACK_BEHAVIOR(callback
);
564 ASSERT_EQ(PP_OK
, callback
.result());
566 // Write some data to have a non-zero file size.
567 callback
.WaitForResult(file_io
.Write(0, "test", 4, callback
.GetCallback()));
568 CHECK_CALLBACK_BEHAVIOR(callback
);
569 ASSERT_EQ(4, callback
.result());
571 const PP_Time last_access_time
= 123 * 24 * 3600.0;
572 // last_modified_time's granularity is 2 seconds
573 // NOTE: In NaCl on Windows, NaClDescIO uses _fstat64 to retrieve file info.
574 // This function returns strange values for very small time values (near the
575 // Unix Epoch). For a value like 246.0, it returns -1. For larger values, it
576 // returns values that are exactly an hour less. The value below is handled
577 // correctly, and is only 100 days after the start of Unix time.
578 const PP_Time last_modified_time
= 100 * 24 * 3600.0;
579 callback
.WaitForResult(file_io
.Touch(last_access_time
, last_modified_time
,
580 callback
.GetCallback()));
581 CHECK_CALLBACK_BEHAVIOR(callback
);
582 ASSERT_EQ(PP_OK
, callback
.result());
585 callback
.WaitForResult(file_io
.Query(&info
, callback
.GetCallback()));
586 CHECK_CALLBACK_BEHAVIOR(callback
);
587 ASSERT_EQ(PP_OK
, callback
.result());
589 if ((info
.size
!= 4) ||
590 (info
.type
!= PP_FILETYPE_REGULAR
) ||
591 (info
.system_type
!= PP_FILESYSTEMTYPE_LOCALTEMPORARY
) ||
592 (info
.last_access_time
!= last_access_time
) ||
593 (info
.last_modified_time
!= last_modified_time
))
594 return "FileIO::Query() has returned bad data.";
596 // Call |Query()| again, to make sure it works a second time.
597 callback
.WaitForResult(file_io
.Query(&info
, callback
.GetCallback()));
598 CHECK_CALLBACK_BEHAVIOR(callback
);
599 ASSERT_EQ(PP_OK
, callback
.result());
604 std::string
TestFileIO::TestAbortCalls() {
605 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
607 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
608 pp::FileRef
file_ref(file_system
, "/file_abort_calls");
609 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
610 CHECK_CALLBACK_BEHAVIOR(callback
);
611 ASSERT_EQ(PP_OK
, callback
.result());
613 int32_t rv
= PP_ERROR_FAILED
;
614 // First, create a file on which to do ops.
616 pp::FileIO
file_io(instance_
);
617 callback
.WaitForResult(
618 file_io
.Open(file_ref
,
619 PP_FILEOPENFLAG_CREATE
| PP_FILEOPENFLAG_WRITE
,
620 callback
.GetCallback()));
621 CHECK_CALLBACK_BEHAVIOR(callback
);
622 ASSERT_EQ(PP_OK
, callback
.result());
624 // N.B.: Should write at least 3 bytes.
625 rv
= WriteEntireBuffer(instance_
->pp_instance(), &file_io
, 0,
626 "foobarbazquux", callback_type());
627 ASSERT_EQ(PP_OK
, rv
);
632 rv
= pp::FileIO(instance_
)
633 .Open(file_ref
, PP_FILEOPENFLAG_READ
, callback
.GetCallback());
635 callback
.WaitForAbortResult(rv
);
636 CHECK_CALLBACK_BEHAVIOR(callback
);
640 PP_FileInfo info
= { 0 };
641 // Save a copy and make sure |info| doesn't get written to if it is aborted.
642 PP_FileInfo info_copy
;
643 memcpy(&info_copy
, &info
, sizeof(info
));
645 pp::FileIO
file_io(instance_
);
646 callback
.WaitForResult(file_io
.Open(file_ref
, PP_FILEOPENFLAG_READ
,
647 callback
.GetCallback()));
648 CHECK_CALLBACK_BEHAVIOR(callback
);
649 ASSERT_EQ(PP_OK
, callback
.result());
651 rv
= file_io
.Query(&info
, callback
.GetCallback());
652 } // Destroy |file_io|.
653 callback
.WaitForResult(rv
);
654 CHECK_CALLBACK_BEHAVIOR(callback
);
655 if (callback_type() == PP_BLOCKING
) {
656 ASSERT_EQ(callback
.result(), PP_OK
);
657 // The operation completed synchronously, so |info| should have changed.
658 ASSERT_NE(0, memcmp(&info_copy
, &info
, sizeof(info
)));
660 ASSERT_EQ(callback
.result(), PP_ERROR_ABORTED
);
661 ASSERT_EQ(0, memcmp(&info_copy
, &info
, sizeof(info
)));
668 pp::FileIO
file_io(instance_
);
669 callback
.WaitForResult(file_io
.Open(file_ref
, PP_FILEOPENFLAG_WRITE
,
670 callback
.GetCallback()));
671 CHECK_CALLBACK_BEHAVIOR(callback
);
672 ASSERT_EQ(PP_OK
, callback
.result());
674 rv
= file_io
.Touch(0, 0, callback
.GetCallback());
675 } // Destroy |file_io|.
676 callback
.WaitForAbortResult(rv
);
677 CHECK_CALLBACK_BEHAVIOR(callback
);
684 pp::FileIO
file_io(instance_
);
685 callback
.WaitForResult(file_io
.Open(file_ref
, PP_FILEOPENFLAG_READ
,
686 callback
.GetCallback()));
687 CHECK_CALLBACK_BEHAVIOR(callback
);
688 ASSERT_EQ(PP_OK
, callback
.result());
690 rv
= file_io
.Read(0, buf
, sizeof(buf
), callback
.GetCallback());
691 } // Destroy |file_io|.
692 // Save a copy to make sure buf isn't written to in the async case.
694 memcpy(&buf_copy
, &buf
, sizeof(buf
));
695 callback
.WaitForResult(rv
);
696 CHECK_CALLBACK_BEHAVIOR(callback
);
697 if (callback_type() == PP_BLOCKING
) {
698 ASSERT_EQ(callback
.result(), sizeof(buf
));
700 ASSERT_EQ(callback
.result(), PP_ERROR_ABORTED
);
701 ASSERT_EQ(0, memcmp(&buf_copy
, &buf
, sizeof(buf
)));
709 pp::FileIO
file_io(instance_
);
710 callback
.WaitForResult(file_io
.Open(file_ref
, PP_FILEOPENFLAG_WRITE
,
711 callback
.GetCallback()));
712 CHECK_CALLBACK_BEHAVIOR(callback
);
713 ASSERT_EQ(PP_OK
, callback
.result());
715 rv
= file_io
.Write(0, buf
, sizeof(buf
), callback
.GetCallback());
716 } // Destroy |file_io|.
717 callback
.WaitForResult(rv
);
718 CHECK_CALLBACK_BEHAVIOR(callback
);
719 if (callback_type() == PP_BLOCKING
)
720 ASSERT_EQ(callback
.result(), sizeof(buf
));
722 ASSERT_EQ(callback
.result(), PP_ERROR_ABORTED
);
725 // Abort |SetLength()|.
728 pp::FileIO
file_io(instance_
);
729 callback
.WaitForResult(file_io
.Open(file_ref
, PP_FILEOPENFLAG_READ
,
730 callback
.GetCallback()));
731 CHECK_CALLBACK_BEHAVIOR(callback
);
732 ASSERT_EQ(PP_OK
, callback
.result());
734 rv
= file_io
.SetLength(3, callback
.GetCallback());
735 } // Destroy |file_io|.
736 callback
.WaitForAbortResult(rv
);
737 CHECK_CALLBACK_BEHAVIOR(callback
);
743 pp::FileIO
file_io(instance_
);
744 callback
.WaitForResult(file_io
.Open(file_ref
, PP_FILEOPENFLAG_WRITE
,
745 callback
.GetCallback()));
746 CHECK_CALLBACK_BEHAVIOR(callback
);
747 ASSERT_EQ(PP_OK
, callback
.result());
749 rv
= file_io
.Flush(callback
.GetCallback());
750 } // Destroy |file_io|.
751 callback
.WaitForAbortResult(rv
);
752 CHECK_CALLBACK_BEHAVIOR(callback
);
758 std::string
TestFileIO::TestParallelReads() {
759 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
760 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
761 pp::FileRef
file_ref(file_system
, "/file_parallel_reads");
762 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
763 CHECK_CALLBACK_BEHAVIOR(callback
);
764 ASSERT_EQ(PP_OK
, callback
.result());
766 pp::FileIO
file_io(instance_
);
767 callback
.WaitForResult(file_io
.Open(file_ref
,
768 PP_FILEOPENFLAG_CREATE
|
769 PP_FILEOPENFLAG_TRUNCATE
|
770 PP_FILEOPENFLAG_READ
|
771 PP_FILEOPENFLAG_WRITE
,
772 callback
.GetCallback()));
773 CHECK_CALLBACK_BEHAVIOR(callback
);
774 ASSERT_EQ(PP_OK
, callback
.result());
776 // Set up testing contents.
777 int32_t rv
= WriteEntireBuffer(instance_
->pp_instance(), &file_io
, 0,
778 "abcdefghijkl", callback_type());
779 ASSERT_EQ(PP_OK
, rv
);
781 // Parallel read operations.
782 const char* border
= "__border__";
783 const int32_t border_size
= strlen(border
);
785 TestCompletionCallback
callback_1(instance_
->pp_instance(), callback_type());
786 int32_t read_offset_1
= 0;
788 std::vector
<char> extended_buf_1(border_size
* 2 + size_1
);
789 char* buf_1
= &extended_buf_1
[border_size
];
790 memcpy(&extended_buf_1
[0], border
, border_size
);
791 memcpy(buf_1
+ size_1
, border
, border_size
);
793 TestCompletionCallback
callback_2(instance_
->pp_instance(), callback_type());
794 int32_t read_offset_2
= size_1
;
796 std::vector
<char> extended_buf_2(border_size
* 2 + size_2
);
797 char* buf_2
= &extended_buf_2
[border_size
];
798 memcpy(&extended_buf_2
[0], border
, border_size
);
799 memcpy(buf_2
+ size_2
, border
, border_size
);
801 int32_t rv_1
= PP_OK
;
802 int32_t rv_2
= PP_OK
;
803 while (size_1
>= 0 && size_2
>= 0 && size_1
+ size_2
> 0) {
805 rv_1
= file_io
.Read(read_offset_1
, buf_1
, size_1
,
806 callback_1
.GetCallback());
809 rv_2
= file_io
.Read(read_offset_2
, buf_2
, size_2
,
810 callback_2
.GetCallback());
813 callback_1
.WaitForResult(rv_1
);
814 CHECK_CALLBACK_BEHAVIOR(callback_1
);
815 ASSERT_TRUE(callback_1
.result() > 0);
816 read_offset_1
+= callback_1
.result();
817 buf_1
+= callback_1
.result();
818 size_1
-= callback_1
.result();
822 callback_2
.WaitForResult(rv_2
);
823 CHECK_CALLBACK_BEHAVIOR(callback_2
);
824 ASSERT_TRUE(callback_2
.result() > 0);
825 read_offset_2
+= callback_2
.result();
826 buf_2
+= callback_2
.result();
827 size_2
-= callback_2
.result();
831 // If |size_1| or |size_2| is not 0, we have invoked wrong callback(s).
832 ASSERT_EQ(0, size_1
);
833 ASSERT_EQ(0, size_2
);
835 // Make sure every read operation writes into the correct buffer.
836 const char expected_result_1
[] = "__border__abc__border__";
837 const char expected_result_2
[] = "__border__defghijkl__border__";
838 ASSERT_TRUE(strncmp(&extended_buf_1
[0], expected_result_1
,
839 strlen(expected_result_1
)) == 0);
840 ASSERT_TRUE(strncmp(&extended_buf_2
[0], expected_result_2
,
841 strlen(expected_result_2
)) == 0);
845 std::string
TestFileIO::TestParallelWrites() {
846 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
847 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
848 pp::FileRef
file_ref(file_system
, "/file_parallel_writes");
849 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
850 CHECK_CALLBACK_BEHAVIOR(callback
);
851 ASSERT_EQ(PP_OK
, callback
.result());
853 pp::FileIO
file_io(instance_
);
854 callback
.WaitForResult(file_io
.Open(file_ref
,
855 PP_FILEOPENFLAG_CREATE
|
856 PP_FILEOPENFLAG_TRUNCATE
|
857 PP_FILEOPENFLAG_READ
|
858 PP_FILEOPENFLAG_WRITE
,
859 callback
.GetCallback()));
860 CHECK_CALLBACK_BEHAVIOR(callback
);
861 ASSERT_EQ(PP_OK
, callback
.result());
863 // Parallel write operations.
864 TestCompletionCallback
callback_1(instance_
->pp_instance(), callback_type());
865 int32_t write_offset_1
= 0;
866 const char* buf_1
= "abc";
867 int32_t size_1
= strlen(buf_1
);
869 TestCompletionCallback
callback_2(instance_
->pp_instance(), callback_type());
870 int32_t write_offset_2
= size_1
;
871 const char* buf_2
= "defghijkl";
872 int32_t size_2
= strlen(buf_2
);
874 int32_t rv_1
= PP_OK
;
875 int32_t rv_2
= PP_OK
;
876 while (size_1
>= 0 && size_2
>= 0 && size_1
+ size_2
> 0) {
878 rv_1
= file_io
.Write(write_offset_1
, buf_1
, size_1
,
879 callback_1
.GetCallback());
882 rv_2
= file_io
.Write(write_offset_2
, buf_2
, size_2
,
883 callback_2
.GetCallback());
887 callback_1
.WaitForResult(rv_1
);
888 CHECK_CALLBACK_BEHAVIOR(callback_1
);
889 ASSERT_TRUE(callback_1
.result() > 0);
890 write_offset_1
+= callback_1
.result();
891 buf_1
+= callback_1
.result();
892 size_1
-= callback_1
.result();
896 callback_2
.WaitForResult(rv_2
);
897 CHECK_CALLBACK_BEHAVIOR(callback_2
);
898 ASSERT_TRUE(callback_2
.result() > 0);
899 write_offset_2
+= callback_2
.result();
900 buf_2
+= callback_2
.result();
901 size_2
-= callback_2
.result();
905 // If |size_1| or |size_2| is not 0, we have invoked wrong callback(s).
906 ASSERT_EQ(0, size_1
);
907 ASSERT_EQ(0, size_2
);
909 // Check the file contents.
910 std::string read_buffer
;
911 int32_t rv
= ReadEntireFile(instance_
->pp_instance(), &file_io
, 0,
912 &read_buffer
, callback_type());
913 ASSERT_EQ(PP_OK
, rv
);
914 ASSERT_EQ(std::string("abcdefghijkl"), read_buffer
);
919 std::string
TestFileIO::TestNotAllowMixedReadWrite() {
920 if (callback_type() == PP_BLOCKING
) {
921 // This test does not make sense for blocking callbacks.
924 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
926 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
927 pp::FileRef
file_ref(file_system
, "/file_not_allow_mixed_read_write");
928 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
929 CHECK_CALLBACK_BEHAVIOR(callback
);
930 ASSERT_EQ(PP_OK
, callback
.result());
932 pp::FileIO
file_io(instance_
);
933 callback
.WaitForResult(file_io
.Open(file_ref
,
934 PP_FILEOPENFLAG_CREATE
|
935 PP_FILEOPENFLAG_TRUNCATE
|
936 PP_FILEOPENFLAG_READ
|
937 PP_FILEOPENFLAG_WRITE
,
938 callback
.GetCallback()));
939 CHECK_CALLBACK_BEHAVIOR(callback
);
940 ASSERT_EQ(PP_OK
, callback
.result());
942 TestCompletionCallback
callback_1(instance_
->pp_instance(), PP_REQUIRED
);
943 int32_t write_offset_1
= 0;
944 const char* buf_1
= "mnopqrstuvw";
945 int32_t rv_1
= file_io
.Write(write_offset_1
, buf_1
, strlen(buf_1
),
946 callback_1
.GetCallback());
947 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, rv_1
);
949 TestCompletionCallback
callback_2(instance_
->pp_instance(), callback_type());
950 int32_t read_offset_2
= 4;
952 callback_2
.WaitForResult(file_io
.Read(read_offset_2
, buf_2
, sizeof(buf_2
),
953 callback_2
.GetCallback()));
954 CHECK_CALLBACK_BEHAVIOR(callback_2
);
955 ASSERT_EQ(PP_ERROR_INPROGRESS
, callback_2
.result());
956 callback_1
.WaitForResult(rv_1
);
957 CHECK_CALLBACK_BEHAVIOR(callback_1
);
959 // Cannot query while a write is pending.
960 rv_1
= file_io
.Write(write_offset_1
, buf_1
, strlen(buf_1
),
961 callback_1
.GetCallback());
962 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, rv_1
);
964 callback_2
.WaitForResult(file_io
.Query(&info
, callback_2
.GetCallback()));
965 CHECK_CALLBACK_BEHAVIOR(callback_2
);
966 ASSERT_EQ(PP_ERROR_INPROGRESS
, callback_2
.result());
967 callback_1
.WaitForResult(rv_1
);
968 CHECK_CALLBACK_BEHAVIOR(callback_1
);
970 // Cannot touch while a write is pending.
971 rv_1
= file_io
.Write(write_offset_1
, buf_1
, strlen(buf_1
),
972 callback_1
.GetCallback());
973 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, rv_1
);
974 callback_2
.WaitForResult(file_io
.Touch(1234.0, 5678.0,
975 callback_2
.GetCallback()));
976 CHECK_CALLBACK_BEHAVIOR(callback_2
);
977 ASSERT_EQ(PP_ERROR_INPROGRESS
, callback_2
.result());
978 callback_1
.WaitForResult(rv_1
);
979 CHECK_CALLBACK_BEHAVIOR(callback_1
);
981 // Cannot set length while a write is pending.
982 rv_1
= file_io
.Write(write_offset_1
, buf_1
, strlen(buf_1
),
983 callback_1
.GetCallback());
984 ASSERT_EQ(PP_OK_COMPLETIONPENDING
, rv_1
);
985 callback_2
.WaitForResult(file_io
.SetLength(123, callback_2
.GetCallback()));
986 CHECK_CALLBACK_BEHAVIOR(callback_2
);
987 ASSERT_EQ(PP_ERROR_INPROGRESS
, callback_2
.result());
988 callback_1
.WaitForResult(rv_1
);
989 CHECK_CALLBACK_BEHAVIOR(callback_1
);
994 std::string
TestFileIO::TestWillWriteWillSetLength() {
995 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
997 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
998 pp::FileRef
file_ref(file_system
, "/file_will_write");
999 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
1000 CHECK_CALLBACK_BEHAVIOR(callback
);
1001 ASSERT_EQ(PP_OK
, callback
.result());
1003 pp::FileIO
file_io(instance_
);
1004 callback
.WaitForResult(file_io
.Open(file_ref
,
1005 PP_FILEOPENFLAG_CREATE
|
1006 PP_FILEOPENFLAG_TRUNCATE
|
1007 PP_FILEOPENFLAG_READ
|
1008 PP_FILEOPENFLAG_WRITE
,
1009 callback
.GetCallback()));
1010 CHECK_CALLBACK_BEHAVIOR(callback
);
1011 ASSERT_EQ(PP_OK
, callback
.result());
1013 const PPB_FileIOTrusted
* trusted
= static_cast<const PPB_FileIOTrusted
*>(
1014 pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE
));
1015 ASSERT_TRUE(trusted
);
1017 // Get file descriptor. This is only supported in-process for now, so don't
1018 // test out of process.
1019 const PPB_Testing_Dev
* testing_interface
= GetTestingInterface();
1020 if (testing_interface
&& !testing_interface
->IsOutOfProcess()) {
1021 int32_t fd
= trusted
->GetOSFileDescriptor(file_io
.pp_resource());
1022 ASSERT_TRUE(fd
>= 0);
1025 // Calling WillWrite.
1026 callback
.WaitForResult(trusted
->WillWrite(
1027 file_io
.pp_resource(), 0, 9,
1028 callback
.GetCallback().pp_completion_callback()));
1029 CHECK_CALLBACK_BEHAVIOR(callback
);
1030 ASSERT_EQ(9, callback
.result());
1032 // Writing the actual data.
1033 int32_t rv
= WriteEntireBuffer(instance_
->pp_instance(), &file_io
, 0,
1034 "test_test", callback_type());
1035 ASSERT_EQ(PP_OK
, rv
);
1037 std::string read_buffer
;
1038 rv
= ReadEntireFile(instance_
->pp_instance(), &file_io
, 0, &read_buffer
,
1040 ASSERT_EQ(PP_OK
, rv
);
1041 ASSERT_EQ(std::string("test_test"), read_buffer
);
1043 // Calling WillSetLength.
1044 callback
.WaitForResult(trusted
->WillSetLength(
1045 file_io
.pp_resource(), 4,
1046 callback
.GetCallback().pp_completion_callback()));
1047 CHECK_CALLBACK_BEHAVIOR(callback
);
1048 ASSERT_EQ(PP_OK
, rv
);
1050 // Calling actual SetLength.
1051 callback
.WaitForResult(file_io
.SetLength(4, callback
.GetCallback()));
1052 CHECK_CALLBACK_BEHAVIOR(callback
);
1053 ASSERT_EQ(PP_OK
, rv
);
1055 read_buffer
.clear();
1056 rv
= ReadEntireFile(instance_
->pp_instance(), &file_io
, 0, &read_buffer
,
1058 ASSERT_EQ(PP_OK
, rv
);
1059 ASSERT_EQ(std::string("test"), read_buffer
);
1064 std::string
TestFileIO::TestRequestOSFileHandle() {
1065 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
1067 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
1068 pp::FileRef
file_ref(file_system
, "/file_os_fd");
1070 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
1071 ASSERT_EQ(PP_OK
, callback
.result());
1073 pp::FileIO_Private
file_io(instance_
);
1074 callback
.WaitForResult(file_io
.Open(file_ref
,
1075 PP_FILEOPENFLAG_CREATE
|
1076 PP_FILEOPENFLAG_TRUNCATE
|
1077 PP_FILEOPENFLAG_READ
|
1078 PP_FILEOPENFLAG_WRITE
,
1079 callback
.GetCallback()));
1080 ASSERT_EQ(PP_OK
, callback
.result());
1082 TestCompletionCallbackWithOutput
<pp::PassFileHandle
> output_callback(
1083 instance_
->pp_instance(), callback_type());
1084 output_callback
.WaitForResult(
1085 file_io
.RequestOSFileHandle(output_callback
.GetCallback()));
1086 PP_FileHandle handle
= output_callback
.output().Release();
1087 ASSERT_EQ(PP_OK
, output_callback
.result());
1089 if (handle
== PP_kInvalidFileHandle
)
1090 return "FileIO::RequestOSFileHandle() returned a bad file handle.";
1091 #if defined(PPAPI_OS_WIN)
1092 int fd
= _open_osfhandle(reinterpret_cast<intptr_t>(handle
),
1093 _O_RDWR
| _O_BINARY
);
1098 return "FileIO::RequestOSFileHandle() returned a bad file descriptor.";
1100 // Check write(2) for the native FD.
1101 const std::string msg
= "foobar";
1102 ssize_t cnt
= write(fd
, msg
.data(), msg
.size());
1104 return ReportError("write for native FD returned error", errno
);
1105 if (cnt
!= static_cast<ssize_t
>(msg
.size()))
1106 return ReportError("write for native FD count mismatch", cnt
);
1108 // Check lseek(2) for the native FD.
1109 off_t off
= lseek(fd
, 0, SEEK_CUR
);
1110 if (off
== static_cast<off_t
>(-1))
1111 return ReportError("lseek for native FD returned error", errno
);
1112 if (off
!= static_cast<off_t
>(msg
.size()))
1113 return ReportError("lseek for native FD offset mismatch", off
);
1115 off
= lseek(fd
, 0, SEEK_SET
);
1116 if (off
== static_cast<off_t
>(-1))
1117 return ReportError("lseek for native FD returned error", errno
);
1119 return ReportError("lseek for native FD offset mismatch", off
);
1121 // Check read(2) for the native FD.
1122 std::string
buf(msg
.size(), '\0');
1123 cnt
= read(fd
, &buf
[0], msg
.size());
1125 return ReportError("read for native FD returned error", errno
);
1126 if (cnt
!= static_cast<ssize_t
>(msg
.size()))
1127 return ReportError("read for native FD count mismatch", cnt
);
1129 return ReportMismatch("read for native FD", buf
, msg
);
1133 // Calling RequestOSFileHandle with the FileIO that is opened with
1134 // PP_FILEOPENFLAG_EXCLUSIVE used to cause NaCl module to crash while loading.
1135 // This is a regression test for crbug.com/243241.
1136 std::string
TestFileIO::TestRequestOSFileHandleWithOpenExclusive() {
1137 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
1139 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
1140 pp::FileRef
file_ref(file_system
, "/file_os_fd2");
1142 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
1143 ASSERT_EQ(PP_OK
, callback
.result());
1145 // Open with PP_FILEOPENFLAG_CREATE and PP_FILEOPENFLAG_EXCLUSIVE will fail
1146 // if the file already exists. Delete it here to make sure it does not.
1147 callback
.WaitForResult(file_ref
.Delete(callback
.GetCallback()));
1149 pp::FileIO_Private
file_io(instance_
);
1150 callback
.WaitForResult(file_io
.Open(file_ref
,
1151 PP_FILEOPENFLAG_CREATE
|
1152 PP_FILEOPENFLAG_READ
|
1153 PP_FILEOPENFLAG_WRITE
|
1154 PP_FILEOPENFLAG_EXCLUSIVE
,
1155 callback
.GetCallback()));
1156 ASSERT_EQ(PP_OK
, callback
.result());
1158 TestCompletionCallbackWithOutput
<pp::PassFileHandle
> output_callback(
1159 instance_
->pp_instance(), callback_type());
1160 output_callback
.WaitForResult(
1161 file_io
.RequestOSFileHandle(output_callback
.GetCallback()));
1162 PP_FileHandle handle
= output_callback
.output().Release();
1163 if (handle
== PP_kInvalidFileHandle
)
1164 return "FileIO::RequestOSFileHandle() returned a bad file handle.";
1165 ASSERT_EQ(PP_OK
, output_callback
.result());
1170 std::string
TestFileIO::TestMmap() {
1171 #if !defined(PPAPI_OS_WIN)
1172 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
1174 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
1175 pp::FileRef
file_ref(file_system
, "/file_os_fd");
1177 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
1178 ASSERT_EQ(PP_OK
, callback
.result());
1180 pp::FileIO_Private
file_io(instance_
);
1181 callback
.WaitForResult(file_io
.Open(file_ref
,
1182 PP_FILEOPENFLAG_CREATE
|
1183 PP_FILEOPENFLAG_TRUNCATE
|
1184 PP_FILEOPENFLAG_READ
|
1185 PP_FILEOPENFLAG_WRITE
,
1186 callback
.GetCallback()));
1187 ASSERT_EQ(PP_OK
, callback
.result());
1189 TestCompletionCallbackWithOutput
<pp::PassFileHandle
> output_callback(
1190 instance_
->pp_instance(), callback_type());
1191 output_callback
.WaitForResult(
1192 file_io
.RequestOSFileHandle(output_callback
.GetCallback()));
1193 PP_FileHandle handle
= output_callback
.output().Release();
1194 ASSERT_EQ(PP_OK
, output_callback
.result());
1196 if (handle
== PP_kInvalidFileHandle
)
1197 return "FileIO::RequestOSFileHandle() returned a bad file handle.";
1200 return "FileIO::RequestOSFileHandle() returned a bad file descriptor.";
1202 // Check write(2) for the native FD.
1203 const std::string msg
= "foobar";
1204 ssize_t cnt
= write(fd
, msg
.data(), msg
.size());
1206 return ReportError("write for native FD returned error", errno
);
1207 if (cnt
!= static_cast<ssize_t
>(msg
.size()))
1208 return ReportError("write for native FD count mismatch", cnt
);
1210 // BEGIN mmap(2) test with a file handle opened in READ-WRITE mode.
1211 // Check mmap(2) for read.
1213 char* mapped
= reinterpret_cast<char*>(
1214 mmap(NULL
, msg
.size(), PROT_READ
, MAP_PRIVATE
, fd
, 0));
1215 if (mapped
== MAP_FAILED
)
1216 return ReportError("mmap(r) for native FD returned errno", errno
);
1217 // Make sure the buffer is cleared.
1218 std::string buf
= std::string(msg
.size(), '\0');
1219 memcpy(&buf
[0], mapped
, msg
.size());
1221 return ReportMismatch("mmap(r) for native FD", buf
, msg
);
1222 int r
= munmap(mapped
, msg
.size());
1224 return ReportError("munmap for native FD returned error", errno
);
1227 // Check mmap(2) for write with MAP_PRIVATE
1229 char* mapped
= reinterpret_cast<char*>(
1230 mmap(NULL
, msg
.size(), PROT_READ
| PROT_WRITE
, MAP_PRIVATE
, fd
, 0));
1231 if (mapped
== MAP_FAILED
)
1232 return ReportError("mmap(r) for native FD returned errno", errno
);
1233 // Make sure the file is not polluted by writing to privage mmap.
1234 strncpy(mapped
, "baz", 3);
1235 std::string read_buffer
;
1236 ASSERT_TRUE(ReadEntireFileFromFileHandle(fd
, &read_buffer
));
1237 if (msg
!= read_buffer
)
1238 return ReportMismatch("file content != msg", read_buffer
, msg
);
1239 int r
= munmap(mapped
, msg
.size());
1241 return ReportError("munmap for native FD returned error", errno
);
1244 // Check mmap(2) for write with MAP_SHARED.
1246 char* mapped
= reinterpret_cast<char*>(
1247 mmap(NULL
, msg
.size(), PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, 0));
1248 if (mapped
== MAP_FAILED
)
1249 return ReportError("mmap(w) for native FD returned errno", errno
);
1251 strncpy(mapped
, "baz", 3);
1252 std::string read_buffer
;
1253 ASSERT_TRUE(ReadEntireFileFromFileHandle(fd
, &read_buffer
));
1254 if (read_buffer
!= "bazbar")
1255 return ReportMismatch("file content != msg", read_buffer
, "bazbar");
1256 int r
= munmap(mapped
, msg
.size());
1258 return ReportError("munmap for native FD returned error", errno
);
1260 // END mmap(2) test with a file handle opened in READ-WRITE mode.
1263 return ReportError("close for native FD returned error", errno
);
1265 // BEGIN mmap(2) test with a file handle opened in READONLY mode.
1266 file_io
= pp::FileIO_Private(instance_
);
1267 callback
.WaitForResult(file_io
.Open(file_ref
,
1268 PP_FILEOPENFLAG_READ
,
1269 callback
.GetCallback()));
1270 ASSERT_EQ(PP_OK
, callback
.result());
1272 output_callback
= TestCompletionCallbackWithOutput
<pp::PassFileHandle
>(
1273 instance_
->pp_instance(), callback_type());
1274 output_callback
.WaitForResult(
1275 file_io
.RequestOSFileHandle(output_callback
.GetCallback()));
1276 handle
= output_callback
.output().Release();
1277 ASSERT_EQ(PP_OK
, output_callback
.result());
1279 if (handle
== PP_kInvalidFileHandle
)
1280 return "FileIO::RequestOSFileHandle() returned a bad file handle.";
1283 return "FileIO::RequestOSFileHandle() returned a bad file descriptor.";
1285 const std::string msg2
= "bazbar";
1287 // Check mmap(2) for read.
1289 char* mapped
= reinterpret_cast<char*>(
1290 mmap(NULL
, msg2
.size(), PROT_READ
, MAP_PRIVATE
, fd
, 0));
1291 if (mapped
== MAP_FAILED
)
1292 return ReportError("mmap(r) for native FD returned errno", errno
);
1293 // Make sure the buffer is cleared.
1294 std::string buf
= std::string(msg2
.size(), '\0');
1295 memcpy(&buf
[0], mapped
, msg2
.size());
1297 return ReportMismatch("mmap(r) for native FD", buf
, msg2
);
1298 int r
= munmap(mapped
, msg2
.size());
1300 return ReportError("munmap for native FD returned error", errno
);
1303 // Check mmap(2) for write with MAP_PRIVATE
1305 char* mapped
= reinterpret_cast<char*>(
1306 mmap(NULL
, msg2
.size(), PROT_READ
| PROT_WRITE
, MAP_PRIVATE
, fd
, 0));
1307 if (mapped
== MAP_FAILED
)
1308 return ReportError("mmap(r) for native FD returned errno", errno
);
1309 // Make sure the file is not polluted by writing to privage mmap.
1310 strncpy(mapped
, "baz", 3);
1311 std::string read_buffer
;
1312 ASSERT_TRUE(ReadEntireFileFromFileHandle(fd
, &read_buffer
));
1313 if (msg2
!= read_buffer
)
1314 return ReportMismatch("file content != msg2", read_buffer
, msg2
);
1315 int r
= munmap(mapped
, msg2
.size());
1317 return ReportError("munmap for native FD returned error", errno
);
1320 // Check mmap(2) for write with MAP_SHARED.
1322 char* mapped
= reinterpret_cast<char*>(
1323 mmap(NULL
, msg2
.size(), PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, 0));
1324 if (mapped
!= MAP_FAILED
)
1325 return ReportError("mmap(w) for native FD must fail when opened readonly",
1328 // END mmap(2) test with a file handle opened in READONLY mode.
1331 return ReportError("close for native FD returned error", errno
);
1332 #endif // !defined(PPAPI_OS_WIN)
1337 std::string
TestFileIO::MatchOpenExpectations(pp::FileSystem
* file_system
,
1339 size_t expectations
) {
1340 std::string bad_argument
=
1341 "TestFileIO::MatchOpenExpectations has invalid input arguments.";
1342 bool invalid_combination
= !!(expectations
& INVALID_FLAG_COMBINATION
);
1343 if (invalid_combination
) {
1344 if (expectations
!= INVALID_FLAG_COMBINATION
)
1345 return bad_argument
;
1347 // Validate that one and only one of <some_expectation> and
1348 // DONT_<some_expectation> is specified.
1349 for (size_t remains
= expectations
, end
= END_OF_OPEN_EXPECATION_PAIRS
;
1350 end
!= 0; remains
>>= 2, end
>>= 2) {
1351 if (!!(remains
& 1) == !!(remains
& 2))
1352 return bad_argument
;
1355 bool create_if_doesnt_exist
= !!(expectations
& CREATE_IF_DOESNT_EXIST
);
1356 bool open_if_exists
= !!(expectations
& OPEN_IF_EXISTS
);
1357 bool truncate_if_exists
= !!(expectations
& TRUNCATE_IF_EXISTS
);
1359 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
1360 pp::FileRef
existent_file_ref(
1361 *file_system
, "/match_open_expectation_existent_non_empty_file");
1362 pp::FileRef
nonexistent_file_ref(
1363 *file_system
, "/match_open_expectation_nonexistent_file");
1365 // Setup files for test.
1367 callback
.WaitForResult(existent_file_ref
.Delete(callback
.GetCallback()));
1368 CHECK_CALLBACK_BEHAVIOR(callback
);
1369 ASSERT_TRUE(callback
.result() == PP_OK
||
1370 callback
.result() == PP_ERROR_FILENOTFOUND
);
1371 callback
.WaitForResult(nonexistent_file_ref
.Delete(callback
.GetCallback()));
1372 CHECK_CALLBACK_BEHAVIOR(callback
);
1373 ASSERT_TRUE(callback
.result() == PP_OK
||
1374 callback
.result() == PP_ERROR_FILENOTFOUND
);
1376 pp::FileIO
existent_file_io(instance_
);
1377 callback
.WaitForResult(existent_file_io
.Open(
1379 PP_FILEOPENFLAG_CREATE
| PP_FILEOPENFLAG_WRITE
,
1380 callback
.GetCallback()));
1381 CHECK_CALLBACK_BEHAVIOR(callback
);
1382 ASSERT_EQ(PP_OK
, callback
.result());
1383 int32_t rv
= WriteEntireBuffer(instance_
->pp_instance(), &existent_file_io
,
1384 0, "foobar", callback_type());
1385 ASSERT_EQ(PP_OK
, rv
);
1388 pp::FileIO
existent_file_io(instance_
);
1389 callback
.WaitForResult(existent_file_io
.Open(existent_file_ref
, open_flags
,
1390 callback
.GetCallback()));
1391 CHECK_CALLBACK_BEHAVIOR(callback
);
1392 if ((invalid_combination
&& callback
.result() == PP_OK
) ||
1393 (!invalid_combination
&&
1394 ((callback
.result() == PP_OK
) != open_if_exists
))) {
1395 return ReportOpenError(open_flags
);
1398 if (!invalid_combination
&& open_if_exists
) {
1400 callback
.WaitForResult(existent_file_io
.Query(&info
,
1401 callback
.GetCallback()));
1402 CHECK_CALLBACK_BEHAVIOR(callback
);
1403 ASSERT_EQ(PP_OK
, callback
.result());
1404 if (truncate_if_exists
!= (info
.size
== 0))
1405 return ReportOpenError(open_flags
);
1408 pp::FileIO
nonexistent_file_io(instance_
);
1409 callback
.WaitForResult(nonexistent_file_io
.Open(nonexistent_file_ref
,
1411 callback
.GetCallback()));
1412 CHECK_CALLBACK_BEHAVIOR(callback
);
1413 if ((invalid_combination
&& callback
.result() == PP_OK
) ||
1414 (!invalid_combination
&&
1415 ((callback
.result() == PP_OK
) != create_if_doesnt_exist
))) {
1416 return ReportOpenError(open_flags
);
1419 return std::string();
1422 // TODO(viettrungluu): Test Close(). crbug.com/69457