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.
5 #include "ppapi/tests/test_file_ref.h"
10 #include "ppapi/c/pp_errors.h"
11 #include "ppapi/c/ppb_file_io.h"
12 #include "ppapi/c/dev/ppb_testing_dev.h"
13 #include "ppapi/cpp/dev/directory_entry_dev.h"
14 #include "ppapi/cpp/dev/directory_reader_dev.h"
15 #include "ppapi/cpp/file_io.h"
16 #include "ppapi/cpp/file_ref.h"
17 #include "ppapi/cpp/file_system.h"
18 #include "ppapi/cpp/instance.h"
19 #include "ppapi/cpp/module.h"
20 #include "ppapi/cpp/url_loader.h"
21 #include "ppapi/cpp/url_request_info.h"
22 #include "ppapi/cpp/url_response_info.h"
23 #include "ppapi/tests/test_utils.h"
24 #include "ppapi/tests/testing_instance.h"
26 REGISTER_TEST_CASE(FileRef
);
30 const char* kPersFileName
= "persistent";
31 const char* kTempFileName
= "temporary";
32 const char* kParentPath
= "/foo/bar";
33 const char* kPersFilePath
= "/foo/bar/persistent";
34 const char* kTempFilePath
= "/foo/bar/temporary";
35 const char* kTerribleName
= "!@#$%^&*()-_=+{}[] ;:'\"|`~\t\n\r\b?";
37 std::string
ReportMismatch(const std::string
& method_name
,
38 const std::string
& returned_result
,
39 const std::string
& expected_result
) {
40 return method_name
+ " returned '" + returned_result
+ "'; '" +
41 expected_result
+ "' expected.";
46 bool TestFileRef::Init() {
47 return CheckTestingInterface() && EnsureRunningOverHTTP();
50 std::string
TestFileRef::MakeExternalFileRef(pp::FileRef
* file_ref_ext
) {
51 pp::URLRequestInfo
request(instance_
);
52 request
.SetURL("test_url_loader_data/hello.txt");
53 request
.SetStreamToFile(true);
55 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
57 pp::URLLoader
loader(instance_
);
58 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
59 CHECK_CALLBACK_BEHAVIOR(callback
);
60 ASSERT_EQ(PP_OK
, callback
.result());
62 pp::URLResponseInfo
response_info(loader
.GetResponseInfo());
63 ASSERT_FALSE(response_info
.is_null());
64 ASSERT_EQ(200, response_info
.GetStatusCode());
66 *file_ref_ext
= pp::FileRef(response_info
.GetBodyAsFileRef());
67 ASSERT_EQ(PP_FILESYSTEMTYPE_EXTERNAL
, file_ref_ext
->GetFileSystemType());
71 void TestFileRef::RunTests(const std::string
& filter
) {
72 RUN_CALLBACK_TEST(TestFileRef
, Create
, filter
);
73 RUN_CALLBACK_TEST(TestFileRef
, GetFileSystemType
, filter
);
74 RUN_CALLBACK_TEST(TestFileRef
, GetName
, filter
);
75 RUN_CALLBACK_TEST(TestFileRef
, GetPath
, filter
);
76 RUN_CALLBACK_TEST(TestFileRef
, GetParent
, filter
);
77 RUN_CALLBACK_TEST(TestFileRef
, MakeDirectory
, filter
);
78 RUN_CALLBACK_TEST(TestFileRef
, QueryAndTouchFile
, filter
);
79 RUN_CALLBACK_TEST(TestFileRef
, DeleteFileAndDirectory
, filter
);
80 RUN_CALLBACK_TEST(TestFileRef
, RenameFileAndDirectory
, filter
);
81 RUN_CALLBACK_TEST(TestFileRef
, Query
, filter
);
82 RUN_CALLBACK_TEST(TestFileRef
, FileNameEscaping
, filter
);
85 std::string
TestFileRef::TestCreate() {
86 std::vector
<std::string
> invalid_paths
;
87 invalid_paths
.push_back("invalid_path"); // no '/' at the first character
88 invalid_paths
.push_back(std::string()); // empty path
89 // The following are directory traversal checks
90 invalid_paths
.push_back("..");
91 invalid_paths
.push_back("/../invalid_path");
92 invalid_paths
.push_back("/../../invalid_path");
93 invalid_paths
.push_back("/invalid/../../path");
94 const size_t num_invalid_paths
= invalid_paths
.size();
96 pp::FileSystem
file_system_pers(
97 instance_
, PP_FILESYSTEMTYPE_LOCALPERSISTENT
);
98 pp::FileSystem
file_system_temp(
99 instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
100 for (size_t j
= 0; j
< num_invalid_paths
; ++j
) {
101 pp::FileRef
file_ref_pers(file_system_pers
, invalid_paths
[j
].c_str());
102 if (file_ref_pers
.pp_resource() != 0) {
103 return "file_ref_pers expected to be invalid for path: " +
106 pp::FileRef
file_ref_temp(file_system_temp
, invalid_paths
[j
].c_str());
107 if (file_ref_temp
.pp_resource() != 0) {
108 return "file_ref_temp expected to be invalid for path: " +
115 std::string
TestFileRef::TestGetFileSystemType() {
116 pp::FileSystem
file_system_pers(
117 instance_
, PP_FILESYSTEMTYPE_LOCALPERSISTENT
);
118 pp::FileSystem
file_system_temp(
119 instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
121 pp::FileRef
file_ref_pers(file_system_pers
, kPersFilePath
);
122 if (file_ref_pers
.GetFileSystemType() != PP_FILESYSTEMTYPE_LOCALPERSISTENT
)
123 return "file_ref_pers expected to be persistent.";
125 pp::FileRef
file_ref_temp(file_system_temp
, kTempFilePath
);
126 if (file_ref_temp
.GetFileSystemType() != PP_FILESYSTEMTYPE_LOCALTEMPORARY
)
127 return "file_ref_temp expected to be temporary.";
129 pp::FileRef file_ref_ext
;
130 std::string result
= MakeExternalFileRef(&file_ref_ext
);
136 std::string
TestFileRef::TestGetName() {
137 pp::FileSystem
file_system_pers(
138 instance_
, PP_FILESYSTEMTYPE_LOCALPERSISTENT
);
139 pp::FileSystem
file_system_temp(
140 instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
142 pp::FileRef
file_ref_pers(file_system_pers
, kPersFilePath
);
143 std::string name
= file_ref_pers
.GetName().AsString();
144 if (name
!= kPersFileName
)
145 return ReportMismatch("FileRef::GetName", name
, kPersFileName
);
147 pp::FileRef
file_ref_temp(file_system_temp
, kTempFilePath
);
148 name
= file_ref_temp
.GetName().AsString();
149 if (name
!= kTempFileName
)
150 return ReportMismatch("FileRef::GetName", name
, kTempFileName
);
152 // Test the "/" case.
153 pp::FileRef
file_ref_slash(file_system_temp
, "/");
154 name
= file_ref_slash
.GetName().AsString();
156 return ReportMismatch("FileRef::GetName", name
, "/");
158 pp::URLRequestInfo
request(instance_
);
159 request
.SetURL("test_url_loader_data/hello.txt");
160 request
.SetStreamToFile(true);
162 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
164 pp::URLLoader
loader(instance_
);
165 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
166 CHECK_CALLBACK_BEHAVIOR(callback
);
167 ASSERT_EQ(PP_OK
, callback
.result());
169 pp::URLResponseInfo
response_info(loader
.GetResponseInfo());
170 ASSERT_FALSE(response_info
.is_null());
171 ASSERT_EQ(200, response_info
.GetStatusCode());
173 pp::FileRef
file_ref_ext(response_info
.GetBodyAsFileRef());
174 name
= file_ref_ext
.GetName().AsString();
175 ASSERT_FALSE(name
.empty());
180 std::string
TestFileRef::TestGetPath() {
181 pp::FileSystem
file_system_pers(
182 instance_
, PP_FILESYSTEMTYPE_LOCALPERSISTENT
);
183 pp::FileSystem
file_system_temp(
184 instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
186 pp::FileRef
file_ref_pers(file_system_pers
, kPersFilePath
);
187 ASSERT_EQ(kPersFilePath
, file_ref_pers
.GetPath().AsString());
189 pp::FileRef
file_ref_temp(file_system_temp
, kTempFilePath
);
190 ASSERT_EQ(kTempFilePath
, file_ref_temp
.GetPath().AsString());
192 pp::URLRequestInfo
request(instance_
);
193 request
.SetURL("test_url_loader_data/hello.txt");
194 request
.SetStreamToFile(true);
196 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
198 pp::URLLoader
loader(instance_
);
199 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
200 CHECK_CALLBACK_BEHAVIOR(callback
);
201 ASSERT_EQ(PP_OK
, callback
.result());
203 pp::URLResponseInfo
response_info(loader
.GetResponseInfo());
204 ASSERT_FALSE(response_info
.is_null());
205 ASSERT_EQ(200, response_info
.GetStatusCode());
207 pp::FileRef
file_ref_ext(response_info
.GetBodyAsFileRef());
208 ASSERT_TRUE(file_ref_ext
.GetPath().is_undefined());
213 std::string
TestFileRef::TestGetParent() {
214 pp::FileSystem
file_system_pers(
215 instance_
, PP_FILESYSTEMTYPE_LOCALPERSISTENT
);
216 pp::FileSystem
file_system_temp(
217 instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
219 pp::FileRef
file_ref_pers(file_system_pers
, kPersFilePath
);
220 ASSERT_EQ(kParentPath
, file_ref_pers
.GetParent().GetPath().AsString());
222 pp::FileRef
file_ref_temp(file_system_temp
, kTempFilePath
);
223 ASSERT_EQ(kParentPath
, file_ref_temp
.GetParent().GetPath().AsString());
225 // Test the "/" case.
226 pp::FileRef
file_ref_slash(file_system_temp
, "/");
227 ASSERT_EQ("/", file_ref_slash
.GetParent().GetPath().AsString());
229 // Test the "/foo" case (the parent is "/").
230 pp::FileRef
file_ref_with_root_parent(file_system_temp
, "/foo");
231 ASSERT_EQ("/", file_ref_with_root_parent
.GetParent().GetPath().AsString());
233 pp::URLRequestInfo
request(instance_
);
234 request
.SetURL("test_url_loader_data/hello.txt");
235 request
.SetStreamToFile(true);
237 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
239 pp::URLLoader
loader(instance_
);
240 callback
.WaitForResult(loader
.Open(request
, callback
.GetCallback()));
241 CHECK_CALLBACK_BEHAVIOR(callback
);
242 ASSERT_EQ(PP_OK
, callback
.result());
244 pp::URLResponseInfo
response_info(loader
.GetResponseInfo());
245 ASSERT_FALSE(response_info
.is_null());
246 ASSERT_EQ(200, response_info
.GetStatusCode());
248 pp::FileRef
file_ref_ext(response_info
.GetBodyAsFileRef());
249 ASSERT_TRUE(file_ref_ext
.GetParent().is_null());
254 std::string
TestFileRef::TestMakeDirectory() {
255 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
258 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
259 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
260 CHECK_CALLBACK_BEHAVIOR(callback
);
261 ASSERT_EQ(PP_OK
, callback
.result());
264 pp::FileRef
dir_ref(file_system
, "/test_dir_make_directory");
265 callback
.WaitForResult(dir_ref
.MakeDirectory(callback
.GetCallback()));
266 CHECK_CALLBACK_BEHAVIOR(callback
);
267 ASSERT_EQ(PP_OK
, callback
.result());
269 // MakeDirectory aborted.
270 int32_t rv
= PP_ERROR_FAILED
;
272 rv
= pp::FileRef(file_system
, "/test_dir_make_abort")
273 .MakeDirectory(callback
.GetCallback());
275 callback
.WaitForAbortResult(rv
);
276 CHECK_CALLBACK_BEHAVIOR(callback
);
278 // MakeDirectoryIncludingAncestors.
279 dir_ref
= pp::FileRef(file_system
, "/dir_make_dir_1/dir_make_dir_2");
280 callback
.WaitForResult(
281 dir_ref
.MakeDirectoryIncludingAncestors(callback
.GetCallback()));
282 CHECK_CALLBACK_BEHAVIOR(callback
);
283 ASSERT_EQ(PP_OK
, callback
.result());
285 // MakeDirectoryIncludingAncestors aborted.
287 rv
= pp::FileRef(file_system
, "/dir_make_abort_1/dir_make_abort_2")
288 .MakeDirectoryIncludingAncestors(callback
.GetCallback());
290 callback
.WaitForAbortResult(rv
);
291 CHECK_CALLBACK_BEHAVIOR(callback
);
293 // MakeDirectory with nested path should fail.
294 dir_ref
= pp::FileRef(file_system
, "/dir_make_dir_3/dir_make_dir_4");
295 callback
.WaitForResult(dir_ref
.MakeDirectory(callback
.GetCallback()));
296 CHECK_CALLBACK_BEHAVIOR(callback
);
297 ASSERT_NE(PP_OK
, callback
.result());
302 std::string
TestFileRef::TestQueryAndTouchFile() {
303 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
304 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
305 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
306 CHECK_CALLBACK_BEHAVIOR(callback
);
307 ASSERT_EQ(PP_OK
, callback
.result());
309 pp::FileRef
file_ref(file_system
, "/file_touch");
310 pp::FileIO
file_io(instance_
);
311 callback
.WaitForResult(
312 file_io
.Open(file_ref
,
313 PP_FILEOPENFLAG_CREATE
|
314 PP_FILEOPENFLAG_TRUNCATE
|
315 PP_FILEOPENFLAG_WRITE
,
316 callback
.GetCallback()));
317 CHECK_CALLBACK_BEHAVIOR(callback
);
318 ASSERT_EQ(PP_OK
, callback
.result());
320 // Write some data to have a non-zero file size.
321 callback
.WaitForResult(file_io
.Write(0, "test", 4, callback
.GetCallback()));
322 CHECK_CALLBACK_BEHAVIOR(callback
);
323 ASSERT_EQ(4, callback
.result());
326 // last_access_time's granularity is 1 day
327 // last_modified_time's granularity is 2 seconds
328 const PP_Time last_access_time
= 123 * 24 * 3600.0;
329 const PP_Time last_modified_time
= 246.0;
330 callback
.WaitForResult(file_ref
.Touch(last_access_time
, last_modified_time
,
331 callback
.GetCallback()));
332 CHECK_CALLBACK_BEHAVIOR(callback
);
333 ASSERT_EQ(PP_OK
, callback
.result());
336 int32_t rv
= PP_ERROR_FAILED
;
338 rv
= pp::FileRef(file_system
, "/file_touch_abort")
339 .Touch(last_access_time
, last_modified_time
, callback
.GetCallback());
341 callback
.WaitForResult(rv
);
342 CHECK_CALLBACK_BEHAVIOR(callback
);
343 if (rv
== PP_OK_COMPLETIONPENDING
) {
344 // Touch tried to run asynchronously and should have been aborted.
345 ASSERT_EQ(PP_ERROR_ABORTED
, callback
.result());
347 // Touch ran synchronously and should have failed because the file does not
349 ASSERT_EQ(PP_ERROR_FILENOTFOUND
, callback
.result());
354 callback
.WaitForResult(file_io
.Query(&info
, callback
.GetCallback()));
355 CHECK_CALLBACK_BEHAVIOR(callback
);
356 ASSERT_EQ(PP_OK
, callback
.result());
357 ASSERT_EQ(4, info
.size
);
358 ASSERT_EQ(PP_FILETYPE_REGULAR
, info
.type
);
359 ASSERT_EQ(PP_FILESYSTEMTYPE_LOCALTEMPORARY
, info
.system_type
);
360 ASSERT_EQ(last_access_time
, info
.last_access_time
);
361 ASSERT_EQ(last_modified_time
, info
.last_modified_time
);
363 // Cancellation test.
364 // TODO(viettrungluu): this test causes a bunch of LOG(WARNING)s; investigate.
365 // TODO(viettrungluu): check |info| for late writes.
367 rv
= pp::FileRef(file_system
, "/file_touch").Touch(
368 last_access_time
, last_modified_time
, callback
.GetCallback());
370 callback
.WaitForAbortResult(rv
);
371 CHECK_CALLBACK_BEHAVIOR(callback
);
376 std::string
TestFileRef::TestDeleteFileAndDirectory() {
377 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
378 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
379 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
380 CHECK_CALLBACK_BEHAVIOR(callback
);
381 ASSERT_EQ(PP_OK
, callback
.result());
383 pp::FileRef
file_ref(file_system
, "/file_delete");
384 pp::FileIO
file_io(instance_
);
385 callback
.WaitForResult(
386 file_io
.Open(file_ref
, PP_FILEOPENFLAG_CREATE
, callback
.GetCallback()));
387 CHECK_CALLBACK_BEHAVIOR(callback
);
388 ASSERT_EQ(PP_OK
, callback
.result());
390 callback
.WaitForResult(file_ref
.Delete(callback
.GetCallback()));
391 CHECK_CALLBACK_BEHAVIOR(callback
);
392 ASSERT_EQ(PP_OK
, callback
.result());
394 pp::FileRef
dir_ref(file_system
, "/dir_delete");
395 callback
.WaitForResult(dir_ref
.MakeDirectory(callback
.GetCallback()));
396 CHECK_CALLBACK_BEHAVIOR(callback
);
397 ASSERT_EQ(PP_OK
, callback
.result());
399 callback
.WaitForResult(dir_ref
.Delete(callback
.GetCallback()));
400 CHECK_CALLBACK_BEHAVIOR(callback
);
401 ASSERT_EQ(PP_OK
, callback
.result());
403 pp::FileRef
nested_dir_ref(file_system
, "/dir_delete_1/dir_delete_2");
404 callback
.WaitForResult(
405 nested_dir_ref
.MakeDirectoryIncludingAncestors(callback
.GetCallback()));
406 CHECK_CALLBACK_BEHAVIOR(callback
);
407 ASSERT_EQ(PP_OK
, callback
.result());
409 // Attempt to delete the parent directory (should fail; it's non-empty).
410 pp::FileRef parent_dir_ref
= nested_dir_ref
.GetParent();
411 callback
.WaitForResult(parent_dir_ref
.Delete(callback
.GetCallback()));
412 CHECK_CALLBACK_BEHAVIOR(callback
);
413 ASSERT_EQ(PP_ERROR_FAILED
, callback
.result());
415 pp::FileRef
nonexistent_file_ref(file_system
, "/nonexistent_file_delete");
416 callback
.WaitForResult(nonexistent_file_ref
.Delete(callback
.GetCallback()));
417 CHECK_CALLBACK_BEHAVIOR(callback
);
418 ASSERT_EQ(PP_ERROR_FILENOTFOUND
, callback
.result());
421 int32_t rv
= PP_ERROR_FAILED
;
423 pp::FileRef
file_ref_abort(file_system
, "/file_delete_abort");
424 pp::FileIO
file_io_abort(instance_
);
425 callback
.WaitForResult(
426 file_io_abort
.Open(file_ref_abort
, PP_FILEOPENFLAG_CREATE
,
427 callback
.GetCallback()));
428 CHECK_CALLBACK_BEHAVIOR(callback
);
429 ASSERT_EQ(PP_OK
, callback
.result());
430 rv
= file_ref_abort
.Delete(callback
.GetCallback());
432 callback
.WaitForAbortResult(rv
);
433 CHECK_CALLBACK_BEHAVIOR(callback
);
438 std::string
TestFileRef::TestRenameFileAndDirectory() {
439 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
440 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
441 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
442 CHECK_CALLBACK_BEHAVIOR(callback
);
443 ASSERT_EQ(PP_OK
, callback
.result());
445 pp::FileRef
file_ref(file_system
, "/file_rename");
446 pp::FileIO
file_io(instance_
);
447 callback
.WaitForResult(
448 file_io
.Open(file_ref
, PP_FILEOPENFLAG_CREATE
, callback
.GetCallback()));
449 CHECK_CALLBACK_BEHAVIOR(callback
);
450 ASSERT_EQ(PP_OK
, callback
.result());
452 pp::FileRef
target_file_ref(file_system
, "/target_file_rename");
453 callback
.WaitForResult(
454 file_ref
.Rename(target_file_ref
, callback
.GetCallback()));
455 CHECK_CALLBACK_BEHAVIOR(callback
);
456 ASSERT_EQ(PP_OK
, callback
.result());
458 pp::FileRef
dir_ref(file_system
, "/dir_rename");
459 callback
.WaitForResult(dir_ref
.MakeDirectory(callback
.GetCallback()));
460 CHECK_CALLBACK_BEHAVIOR(callback
);
461 ASSERT_EQ(PP_OK
, callback
.result());
463 pp::FileRef
target_dir_ref(file_system
, "/target_dir_rename");
464 callback
.WaitForResult(
465 dir_ref
.Rename(target_dir_ref
, callback
.GetCallback()));
466 CHECK_CALLBACK_BEHAVIOR(callback
);
467 ASSERT_EQ(PP_OK
, callback
.result());
469 pp::FileRef
nested_dir_ref(file_system
, "/dir_rename_1/dir_rename_2");
470 callback
.WaitForResult(
471 nested_dir_ref
.MakeDirectoryIncludingAncestors(callback
.GetCallback()));
472 CHECK_CALLBACK_BEHAVIOR(callback
);
473 ASSERT_EQ(PP_OK
, callback
.result());
475 // Try to rename nested directory to the parent name. Should fail.
476 pp::FileRef
target_nested_dir_ref(file_system
, "/dir_rename_1");
477 callback
.WaitForResult(
478 nested_dir_ref
.Rename(target_nested_dir_ref
, callback
.GetCallback()));
479 CHECK_CALLBACK_BEHAVIOR(callback
);
480 ASSERT_EQ(PP_ERROR_FAILED
, callback
.result());
483 // TODO(viettrungluu): Figure out what we want to do if the target file
484 // resource is destroyed before completion.
485 int32_t rv
= PP_ERROR_FAILED
;
486 pp::FileRef
target_file_ref_abort(file_system
,
487 "/target_file_rename_abort");
489 pp::FileRef
file_ref_abort(file_system
, "/file_rename_abort");
490 pp::FileIO
file_io_abort(instance_
);
491 callback
.WaitForResult(
492 file_io_abort
.Open(file_ref_abort
, PP_FILEOPENFLAG_CREATE
,
493 callback
.GetCallback()));
494 CHECK_CALLBACK_BEHAVIOR(callback
);
495 ASSERT_EQ(PP_OK
, callback
.result());
497 rv
= file_ref_abort
.Rename(target_file_ref_abort
, callback
.GetCallback());
499 callback
.WaitForAbortResult(rv
);
500 CHECK_CALLBACK_BEHAVIOR(callback
);
505 std::string
TestFileRef::TestQuery() {
506 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
508 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
509 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
510 CHECK_CALLBACK_BEHAVIOR(callback
);
511 ASSERT_EQ(PP_OK
, callback
.result());
513 pp::FileRef
file_ref(file_system
, "/file");
514 pp::FileIO
file_io(instance_
);
515 callback
.WaitForResult(file_io
.Open(file_ref
, PP_FILEOPENFLAG_CREATE
,
516 callback
.GetCallback()));
517 CHECK_CALLBACK_BEHAVIOR(callback
);
518 ASSERT_EQ(PP_OK
, callback
.result());
520 // We touch the file so we can easily check access and modified time.
521 callback
.WaitForResult(file_io
.Touch(0, 0, callback
.GetCallback()));
522 CHECK_CALLBACK_BEHAVIOR(callback
);
523 ASSERT_EQ(PP_OK
, callback
.result());
525 TestCompletionCallbackWithOutput
<PP_FileInfo
> out_callback(
526 instance_
->pp_instance(), callback_type());
527 out_callback
.WaitForResult(file_ref
.Query(out_callback
.GetCallback()));
528 CHECK_CALLBACK_BEHAVIOR(out_callback
);
529 ASSERT_EQ(PP_OK
, out_callback
.result());
531 PP_FileInfo info
= out_callback
.output();
532 ASSERT_EQ(0, info
.size
);
533 ASSERT_EQ(PP_FILETYPE_REGULAR
, info
.type
);
534 ASSERT_EQ(PP_FILESYSTEMTYPE_LOCALTEMPORARY
, info
.system_type
);
535 ASSERT_DOUBLE_EQ(0.0, info
.last_access_time
);
536 ASSERT_DOUBLE_EQ(0.0, info
.last_modified_time
);
538 // Query a file ref on an external filesystem.
539 pp::FileRef file_ref_ext
;
540 std::string result
= MakeExternalFileRef(&file_ref_ext
);
543 out_callback
.WaitForResult(file_ref_ext
.Query(out_callback
.GetCallback()));
544 CHECK_CALLBACK_BEHAVIOR(out_callback
);
545 if (out_callback
.result() != PP_OK
)
546 return ReportError("Query() result", out_callback
.result());
547 ASSERT_EQ(PP_OK
, out_callback
.result());
549 info
= out_callback
.output();
550 ASSERT_EQ(PP_FILETYPE_REGULAR
, info
.type
);
551 ASSERT_EQ(PP_FILESYSTEMTYPE_EXTERNAL
, info
.system_type
);
553 // We can't touch the file, so just sanity check the times.
554 ASSERT_TRUE(info
.creation_time
>= 0.0);
555 ASSERT_TRUE(info
.last_modified_time
>= 0.0);
556 ASSERT_TRUE(info
.last_access_time
>= 0.0);
558 // Query a file ref for a file that doesn't exist.
559 pp::FileRef
missing_file_ref(file_system
, "/missing_file");
560 out_callback
.WaitForResult(missing_file_ref
.Query(
561 out_callback
.GetCallback()));
562 CHECK_CALLBACK_BEHAVIOR(out_callback
);
563 ASSERT_EQ(PP_ERROR_FILENOTFOUND
, out_callback
.result());
568 std::string
TestFileRef::TestFileNameEscaping() {
569 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
570 pp::FileSystem
file_system(instance_
, PP_FILESYSTEMTYPE_LOCALTEMPORARY
);
571 callback
.WaitForResult(file_system
.Open(1024, callback
.GetCallback()));
572 CHECK_CALLBACK_BEHAVIOR(callback
);
573 ASSERT_EQ(PP_OK
, callback
.result());
575 std::string test_dir_path
= "/dir_for_escaping_test";
576 // Create a directory in which to test.
577 pp::FileRef
test_dir_ref(file_system
, test_dir_path
.c_str());
578 callback
.WaitForResult(test_dir_ref
.MakeDirectory(callback
.GetCallback()));
579 CHECK_CALLBACK_BEHAVIOR(callback
);
580 ASSERT_EQ(PP_OK
, callback
.result());
582 // Create the file with the terrible name.
583 std::string full_file_path
= test_dir_path
+ "/" + kTerribleName
;
584 pp::FileRef
file_ref(file_system
, full_file_path
.c_str());
585 pp::FileIO
file_io(instance_
);
586 callback
.WaitForResult(
587 file_io
.Open(file_ref
, PP_FILEOPENFLAG_CREATE
, callback
.GetCallback()));
588 CHECK_CALLBACK_BEHAVIOR(callback
);
589 ASSERT_EQ(PP_OK
, callback
.result());
591 // DirectoryReader only works out-of-process.
592 if (testing_interface_
->IsOutOfProcess()) {
593 TestCompletionCallbackWithOutput
< std::vector
<pp::DirectoryEntry_Dev
> >
594 output_callback(instance_
->pp_instance(), callback_type());
595 pp::DirectoryReader_Dev
directory_reader(test_dir_ref
);
597 output_callback
.WaitForResult(
598 directory_reader
.ReadEntries(output_callback
.GetCallback()));
599 CHECK_CALLBACK_BEHAVIOR(output_callback
);
600 ASSERT_EQ(PP_OK
, output_callback
.result());
602 std::vector
<pp::DirectoryEntry_Dev
> entries
= output_callback
.output();
603 ASSERT_EQ(1, entries
.size());
604 ASSERT_EQ(kTerribleName
, entries
.front().file_ref().GetName().AsString());