test_file_ref.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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. 4 5#include "ppapi/tests/test_file_ref.h" 6 7#include <stdio.h> 8#include <vector> 9 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" 25 26REGISTER_TEST_CASE(FileRef); 27 28namespace { 29 30const char* kPersFileName = "persistent"; 31const char* kTempFileName = "temporary"; 32const char* kParentPath = "/foo/bar"; 33const char* kPersFilePath = "/foo/bar/persistent"; 34const char* kTempFilePath = "/foo/bar/temporary"; 35#ifndef PPAPI_OS_NACL // Only used for a test that NaCl can't run yet. 36const char* kTerribleName = "!@#$%^&*()-_=+{}[] ;:'\"|`~\t\n\r\b?"; 37#endif 38 39std::string ReportMismatch(const std::string& method_name, 40 const std::string& returned_result, 41 const std::string& expected_result) { 42 return method_name + " returned '" + returned_result + "'; '" + 43 expected_result + "' expected."; 44} 45 46} // namespace 47 48bool TestFileRef::Init() { 49 return CheckTestingInterface() && EnsureRunningOverHTTP(); 50} 51 52void TestFileRef::RunTests(const std::string& filter) { 53 RUN_TEST_FORCEASYNC_AND_NOT(Create, filter); 54 RUN_TEST_FORCEASYNC_AND_NOT(GetFileSystemType, filter); 55 RUN_TEST_FORCEASYNC_AND_NOT(GetName, filter); 56 RUN_TEST_FORCEASYNC_AND_NOT(GetPath, filter); 57 RUN_TEST_FORCEASYNC_AND_NOT(GetParent, filter); 58 RUN_TEST_FORCEASYNC_AND_NOT(MakeDirectory, filter); 59 RUN_TEST_FORCEASYNC_AND_NOT(QueryAndTouchFile, filter); 60 RUN_TEST_FORCEASYNC_AND_NOT(DeleteFileAndDirectory, filter); 61 RUN_TEST_FORCEASYNC_AND_NOT(RenameFileAndDirectory, filter); 62#ifndef PPAPI_OS_NACL // NaCl can't run this test yet. 63 RUN_TEST_FORCEASYNC_AND_NOT(FileNameEscaping, filter); 64#endif 65} 66 67std::string TestFileRef::TestCreate() { 68 std::vector<std::string> invalid_paths; 69 invalid_paths.push_back("invalid_path"); // no '/' at the first character 70 invalid_paths.push_back(""); // empty path 71 // The following are directory traversal checks 72 invalid_paths.push_back(".."); 73 invalid_paths.push_back("/../invalid_path"); 74 invalid_paths.push_back("/../../invalid_path"); 75 invalid_paths.push_back("/invalid/../../path"); 76 const size_t num_invalid_paths = invalid_paths.size(); 77 78 pp::FileSystem file_system_pers( 79 instance_, PP_FILESYSTEMTYPE_LOCALPERSISTENT); 80 pp::FileSystem file_system_temp( 81 instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); 82 for (size_t j = 0; j < num_invalid_paths; ++j) { 83 pp::FileRef file_ref_pers(file_system_pers, invalid_paths[j].c_str()); 84 if (file_ref_pers.pp_resource() != 0) { 85 return "file_ref_pers expected to be invalid for path: " + 86 invalid_paths[j]; 87 } 88 pp::FileRef file_ref_temp(file_system_temp, invalid_paths[j].c_str()); 89 if (file_ref_temp.pp_resource() != 0) { 90 return "file_ref_temp expected to be invalid for path: " + 91 invalid_paths[j]; 92 } 93 } 94 PASS(); 95} 96 97std::string TestFileRef::TestGetFileSystemType() { 98 pp::FileSystem file_system_pers( 99 instance_, PP_FILESYSTEMTYPE_LOCALPERSISTENT); 100 pp::FileSystem file_system_temp( 101 instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); 102 103 pp::FileRef file_ref_pers(file_system_pers, kPersFilePath); 104 if (file_ref_pers.GetFileSystemType() != PP_FILESYSTEMTYPE_LOCALPERSISTENT) 105 return "file_ref_pers expected to be persistent."; 106 107 pp::FileRef file_ref_temp(file_system_temp, kTempFilePath); 108 if (file_ref_temp.GetFileSystemType() != PP_FILESYSTEMTYPE_LOCALTEMPORARY) 109 return "file_ref_temp expected to be temporary."; 110 111 pp::URLRequestInfo request(instance_); 112 request.SetURL("test_url_loader_data/hello.txt"); 113 request.SetStreamToFile(true); 114 115 TestCompletionCallback callback(instance_->pp_instance(), force_async_); 116 117 pp::URLLoader loader(instance_); 118 int32_t rv = loader.Open(request, callback.GetCallback()); 119 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 120 return ReportError("URLLoader::Open force_async", rv); 121 if (rv == PP_OK_COMPLETIONPENDING) 122 rv = callback.WaitForResult(); 123 if (rv != PP_OK) 124 return "URLLoader::Open() failed."; 125 126 pp::URLResponseInfo response_info(loader.GetResponseInfo()); 127 if (response_info.is_null()) 128 return "URLLoader::GetResponseInfo returned null"; 129 int32_t status_code = response_info.GetStatusCode(); 130 if (status_code != 200) 131 return "Unexpected HTTP status code"; 132 133 pp::FileRef file_ref_ext(response_info.GetBodyAsFileRef()); 134 if (file_ref_ext.GetFileSystemType() != PP_FILESYSTEMTYPE_EXTERNAL) 135 return "file_ref_ext expected to be external."; 136 137 PASS(); 138} 139 140std::string TestFileRef::TestGetName() { 141 pp::FileSystem file_system_pers( 142 instance_, PP_FILESYSTEMTYPE_LOCALPERSISTENT); 143 pp::FileSystem file_system_temp( 144 instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); 145 146 pp::FileRef file_ref_pers(file_system_pers, kPersFilePath); 147 std::string name = file_ref_pers.GetName().AsString(); 148 if (name != kPersFileName) 149 return ReportMismatch("FileRef::GetName", name, kPersFileName); 150 151 pp::FileRef file_ref_temp(file_system_temp, kTempFilePath); 152 name = file_ref_temp.GetName().AsString(); 153 if (name != kTempFileName) 154 return ReportMismatch("FileRef::GetName", name, kTempFileName); 155 156 // Test the "/" case. 157 pp::FileRef file_ref_slash(file_system_temp, "/"); 158 name = file_ref_slash.GetName().AsString(); 159 if (name != "/") 160 return ReportMismatch("FileRef::GetName", name, "/"); 161 162 pp::URLRequestInfo request(instance_); 163 request.SetURL("test_url_loader_data/hello.txt"); 164 request.SetStreamToFile(true); 165 166 TestCompletionCallback callback(instance_->pp_instance(), force_async_); 167 168 pp::URLLoader loader(instance_); 169 int32_t rv = loader.Open(request, callback.GetCallback()); 170 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 171 return ReportError("URLLoader::Open force_async", rv); 172 if (rv == PP_OK_COMPLETIONPENDING) 173 rv = callback.WaitForResult(); 174 if (rv != PP_OK) 175 return "URLLoader::Open() failed."; 176 177 pp::URLResponseInfo response_info(loader.GetResponseInfo()); 178 if (response_info.is_null()) 179 return "URLLoader::GetResponseInfo returned null"; 180 int32_t status_code = response_info.GetStatusCode(); 181 if (status_code != 200) 182 return "Unexpected HTTP status code"; 183 184 pp::FileRef file_ref_ext(response_info.GetBodyAsFileRef()); 185 name = file_ref_ext.GetName().AsString(); 186 if (name == "") 187 return ReportMismatch("FileRef::GetName", name, "<a temp file>"); 188 189 PASS(); 190} 191 192std::string TestFileRef::TestGetPath() { 193 pp::FileSystem file_system_pers( 194 instance_, PP_FILESYSTEMTYPE_LOCALPERSISTENT); 195 pp::FileSystem file_system_temp( 196 instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); 197 198 pp::FileRef file_ref_pers(file_system_pers, kPersFilePath); 199 std::string path = file_ref_pers.GetPath().AsString(); 200 if (path != kPersFilePath) 201 return ReportMismatch("FileRef::GetPath", path, kPersFilePath); 202 203 pp::FileRef file_ref_temp(file_system_temp, kTempFilePath); 204 path = file_ref_temp.GetPath().AsString(); 205 if (path != kTempFilePath) 206 return ReportMismatch("FileRef::GetPath", path, kTempFilePath); 207 208 pp::URLRequestInfo request(instance_); 209 request.SetURL("test_url_loader_data/hello.txt"); 210 request.SetStreamToFile(true); 211 212 TestCompletionCallback callback(instance_->pp_instance(), force_async_); 213 214 pp::URLLoader loader(instance_); 215 int32_t rv = loader.Open(request, callback.GetCallback()); 216 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 217 return ReportError("URLLoader::Open force_async", rv); 218 if (rv == PP_OK_COMPLETIONPENDING) 219 rv = callback.WaitForResult(); 220 if (rv != PP_OK) 221 return "URLLoader::Open() failed."; 222 223 pp::URLResponseInfo response_info(loader.GetResponseInfo()); 224 if (response_info.is_null()) 225 return "URLLoader::GetResponseInfo returned null"; 226 int32_t status_code = response_info.GetStatusCode(); 227 if (status_code != 200) 228 return "Unexpected HTTP status code"; 229 230 pp::FileRef file_ref_ext(response_info.GetBodyAsFileRef()); 231 if (!file_ref_ext.GetPath().is_undefined()) 232 return "The path of an external FileRef should be void."; 233 234 PASS(); 235} 236 237std::string TestFileRef::TestGetParent() { 238 pp::FileSystem file_system_pers( 239 instance_, PP_FILESYSTEMTYPE_LOCALPERSISTENT); 240 pp::FileSystem file_system_temp( 241 instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); 242 243 pp::FileRef file_ref_pers(file_system_pers, kPersFilePath); 244 std::string parent_path = file_ref_pers.GetParent().GetPath().AsString(); 245 if (parent_path != kParentPath) 246 return ReportMismatch("FileRef::GetParent", parent_path, kParentPath); 247 248 pp::FileRef file_ref_temp(file_system_temp, kTempFilePath); 249 parent_path = file_ref_temp.GetParent().GetPath().AsString(); 250 if (parent_path != kParentPath) 251 return ReportMismatch("FileRef::GetParent", parent_path, kParentPath); 252 253 // Test the "/" case. 254 pp::FileRef file_ref_slash(file_system_temp, "/"); 255 parent_path = file_ref_slash.GetParent().GetPath().AsString(); 256 if (parent_path != "/") 257 return ReportMismatch("FileRef::GetParent", parent_path, "/"); 258 259 // Test the "/foo" case (the parent is "/"). 260 pp::FileRef file_ref_with_root_parent(file_system_temp, "/foo"); 261 parent_path = file_ref_with_root_parent.GetParent().GetPath().AsString(); 262 if (parent_path != "/") 263 return ReportMismatch("FileRef::GetParent", parent_path, "/"); 264 265 pp::URLRequestInfo request(instance_); 266 request.SetURL("test_url_loader_data/hello.txt"); 267 request.SetStreamToFile(true); 268 269 TestCompletionCallback callback(instance_->pp_instance(), force_async_); 270 271 pp::URLLoader loader(instance_); 272 int32_t rv = loader.Open(request, callback.GetCallback()); 273 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 274 return ReportError("URLLoader::Open force_async", rv); 275 if (rv == PP_OK_COMPLETIONPENDING) 276 rv = callback.WaitForResult(); 277 if (rv != PP_OK) 278 return "URLLoader::Open() failed."; 279 280 pp::URLResponseInfo response_info(loader.GetResponseInfo()); 281 if (response_info.is_null()) 282 return "URLLoader::GetResponseInfo returned null"; 283 int32_t status_code = response_info.GetStatusCode(); 284 if (status_code != 200) 285 return "Unexpected HTTP status code"; 286 287 pp::FileRef file_ref_ext(response_info.GetBodyAsFileRef()); 288 if (!file_ref_ext.GetParent().is_null()) 289 return "The parent of an external FileRef should be null."; 290 291 PASS(); 292} 293 294std::string TestFileRef::TestMakeDirectory() { 295 TestCompletionCallback callback(instance_->pp_instance(), force_async_); 296 297 // Open. 298 pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); 299 int32_t rv = file_system.Open(1024, callback.GetCallback()); 300 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 301 return ReportError("FileSystem::Open force_async", rv); 302 if (rv == PP_OK_COMPLETIONPENDING) 303 rv = callback.WaitForResult(); 304 if (rv != PP_OK) 305 return ReportError("FileSystem::Open", rv); 306 307 // MakeDirectory. 308 pp::FileRef dir_ref(file_system, "/test_dir_make_directory"); 309 rv = dir_ref.MakeDirectory(callback.GetCallback()); 310 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 311 return ReportError("FileSystem::MakeDirectory force_async", rv); 312 if (rv == PP_OK_COMPLETIONPENDING) 313 rv = callback.WaitForResult(); 314 if (rv != PP_OK) 315 return ReportError("FileSystem::MakeDirectory", rv); 316 317 // MakeDirectory aborted. 318 callback.reset_run_count(); 319 rv = pp::FileRef(file_system, "/test_dir_make_abort") 320 .MakeDirectory(callback.GetCallback()); 321 if (callback.run_count() > 0) 322 return "FileSystem::MakeDirectory ran callback synchronously."; 323 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 324 return ReportError("FileSystem::MakeDirectory force_async", rv); 325 if (rv == PP_OK_COMPLETIONPENDING) { 326 rv = callback.WaitForResult(); 327 if (rv != PP_ERROR_ABORTED) 328 return "FileSystem::MakeDirectory not aborted."; 329 } else if (rv != PP_OK) { 330 return ReportError("FileSystem::MakeDirectory", rv); 331 } 332 333 // MakeDirectoryIncludingAncestors. 334 dir_ref = pp::FileRef(file_system, "/dir_make_dir_1/dir_make_dir_2"); 335 rv = dir_ref.MakeDirectoryIncludingAncestors(callback.GetCallback()); 336 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 337 return ReportError("FileSystem::MakeDirectory force_async", rv); 338 if (rv == PP_OK_COMPLETIONPENDING) 339 rv = callback.WaitForResult(); 340 if (rv != PP_OK) 341 return ReportError("FileSystem::MakeDirectoryIncludingAncestors", rv); 342 343 // MakeDirectoryIncludingAncestors aborted. 344 callback.reset_run_count(); 345 rv = pp::FileRef(file_system, "/dir_make_abort_1/dir_make_abort_2") 346 .MakeDirectoryIncludingAncestors(callback.GetCallback()); 347 if (callback.run_count() > 0) { 348 return "FileSystem::MakeDirectoryIncludingAncestors " 349 "ran callback synchronously."; 350 } 351 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 352 return ReportError( 353 "FileSystem::MakeDirectoryIncludingAncestors force_async", rv); 354 if (rv == PP_OK_COMPLETIONPENDING) { 355 rv = callback.WaitForResult(); 356 if (rv != PP_ERROR_ABORTED) 357 return "FileSystem::MakeDirectoryIncludingAncestors not aborted."; 358 } else if (rv != PP_OK) { 359 return ReportError("FileSystem::MakeDirectoryIncludingAncestors", rv); 360 } 361 362 // MakeDirectory with nested path. 363 dir_ref = pp::FileRef(file_system, "/dir_make_dir_3/dir_make_dir_4"); 364 rv = dir_ref.MakeDirectory(callback.GetCallback()); 365 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 366 return ReportError("FileSystem::MakeDirectory force_async", rv); 367 if (rv == PP_OK_COMPLETIONPENDING) 368 rv = callback.WaitForResult(); 369 if (rv == PP_OK) { 370 return "Calling FileSystem::MakeDirectory() with a nested directory path " 371 "should have failed."; 372 } 373 374 PASS(); 375} 376 377std::string TestFileRef::TestQueryAndTouchFile() { 378 TestCompletionCallback callback(instance_->pp_instance(), force_async_); 379 pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); 380 int32_t rv = file_system.Open(1024, callback.GetCallback()); 381 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 382 return ReportError("FileSystem::Open force_async", rv); 383 if (rv == PP_OK_COMPLETIONPENDING) 384 rv = callback.WaitForResult(); 385 if (rv != PP_OK) 386 return ReportError("FileSystem::Open", rv); 387 388 pp::FileRef file_ref(file_system, "/file_touch"); 389 pp::FileIO file_io(instance_); 390 rv = file_io.Open(file_ref, 391 PP_FILEOPENFLAG_CREATE | 392 PP_FILEOPENFLAG_TRUNCATE | 393 PP_FILEOPENFLAG_WRITE, 394 callback.GetCallback()); 395 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 396 return ReportError("FileIO::Open force_async", rv); 397 if (rv == PP_OK_COMPLETIONPENDING) 398 rv = callback.WaitForResult(); 399 if (rv != PP_OK) 400 return ReportError("FileIO::Open", rv); 401 402 // Write some data to have a non-zero file size. 403 rv = file_io.Write(0, "test", 4, callback.GetCallback()); 404 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 405 return ReportError("FileIO::Write force_async", rv); 406 if (rv == PP_OK_COMPLETIONPENDING) 407 rv = callback.WaitForResult(); 408 if (rv != 4) 409 return ReportError("FileIO::Write", rv); 410 411 // Touch. 412 // last_access_time's granularity is 1 day 413 // last_modified_time's granularity is 2 seconds 414 const PP_Time last_access_time = 123 * 24 * 3600.0; 415 const PP_Time last_modified_time = 246.0; 416 rv = file_ref.Touch(last_access_time, last_modified_time, 417 callback.GetCallback()); 418 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 419 return ReportError("FileSystem::Touch force_async", rv); 420 if (rv == PP_OK_COMPLETIONPENDING) 421 rv = callback.WaitForResult(); 422 if (rv != PP_OK) 423 return ReportError("FileSystem::Touch", rv); 424 425 // Touch aborted. 426 callback.reset_run_count(); 427 rv = pp::FileRef(file_system, "/file_touch_abort") 428 .Touch(last_access_time, last_modified_time, callback.GetCallback()); 429 if (callback.run_count() > 0) 430 return "FileSystem::Touch ran callback synchronously."; 431 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 432 return ReportError("FileSystem::Touch force_async", rv); 433 if (rv == PP_OK_COMPLETIONPENDING) { 434 rv = callback.WaitForResult(); 435 if (rv != PP_ERROR_ABORTED) 436 return "FileSystem::Touch not aborted."; 437 } else if (rv != PP_OK) { 438 return ReportError("FileSystem::Touch", rv); 439 } 440 441 // Query. 442 PP_FileInfo info; 443 rv = file_io.Query(&info, callback.GetCallback()); 444 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 445 return ReportError("FileSystem::Query force_async", rv); 446 if (rv == PP_OK_COMPLETIONPENDING) 447 rv = callback.WaitForResult(); 448 if (rv != PP_OK) 449 return ReportError("FileSystem::Query", rv); 450 451 if ((info.size != 4) || 452 (info.type != PP_FILETYPE_REGULAR) || 453 (info.system_type != PP_FILESYSTEMTYPE_LOCALTEMPORARY) || 454 (info.last_access_time != last_access_time) || 455 (info.last_modified_time != last_modified_time)) 456 return "FileSystem::Query() has returned bad data."; 457 458 // Cancellation test. 459 // TODO(viettrungluu): this test causes a bunch of LOG(WARNING)s; investigate. 460 callback.reset_run_count(); 461 // TODO(viettrungluu): check |info| for late writes. 462 rv = pp::FileRef(file_system, "/file_touch").Touch( 463 last_access_time, last_modified_time, callback.GetCallback()); 464 if (callback.run_count() > 0) 465 return "FileSystem::Touch ran callback synchronously."; 466 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 467 return ReportError("FileSystem::Touch force_async", rv); 468 if (rv == PP_OK_COMPLETIONPENDING) { 469 rv = callback.WaitForResult(); 470 if (rv != PP_ERROR_ABORTED) 471 return "FileSystem::Touch not aborted."; 472 } else if (rv != PP_OK) { 473 return ReportError("FileSystem::Touch", rv); 474 } 475 476 PASS(); 477} 478 479std::string TestFileRef::TestDeleteFileAndDirectory() { 480 TestCompletionCallback callback(instance_->pp_instance(), force_async_); 481 pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); 482 int32_t rv = file_system.Open(1024, callback.GetCallback()); 483 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 484 return ReportError("FileSystem::Open force_async", rv); 485 if (rv == PP_OK_COMPLETIONPENDING) 486 rv = callback.WaitForResult(); 487 if (rv != PP_OK) 488 return ReportError("FileSystem::Open", rv); 489 490 pp::FileRef file_ref(file_system, "/file_delete"); 491 pp::FileIO file_io(instance_); 492 rv = file_io.Open(file_ref, PP_FILEOPENFLAG_CREATE, callback.GetCallback()); 493 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 494 return ReportError("FileIO::Open force_async", rv); 495 if (rv == PP_OK_COMPLETIONPENDING) 496 rv = callback.WaitForResult(); 497 if (rv != PP_OK) 498 return ReportError("FileIO::Open", rv); 499 500 rv = file_ref.Delete(callback.GetCallback()); 501 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 502 return ReportError("FileRef::Delete force_async", rv); 503 if (rv == PP_OK_COMPLETIONPENDING) 504 rv = callback.WaitForResult(); 505 if (rv != PP_OK) 506 return ReportError("FileRef::Delete", rv); 507 508 pp::FileRef dir_ref(file_system, "/dir_delete"); 509 rv = dir_ref.MakeDirectory(callback.GetCallback()); 510 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 511 return ReportError("FileRef::MakeDirectory force_async", rv); 512 if (rv == PP_OK_COMPLETIONPENDING) 513 rv = callback.WaitForResult(); 514 if (rv != PP_OK) 515 return ReportError("FileRef::MakeDirectory", rv); 516 517 rv = dir_ref.Delete(callback.GetCallback()); 518 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 519 return ReportError("FileRef::Open force_async", rv); 520 if (rv == PP_OK_COMPLETIONPENDING) 521 rv = callback.WaitForResult(); 522 if (rv != PP_OK) 523 return ReportError("FileRef::Delete", rv); 524 525 pp::FileRef nested_dir_ref(file_system, "/dir_delete_1/dir_delete_2"); 526 rv = nested_dir_ref.MakeDirectoryIncludingAncestors(callback.GetCallback()); 527 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 528 return ReportError("FileRef::Open force_async", rv); 529 if (rv == PP_OK_COMPLETIONPENDING) 530 rv = callback.WaitForResult(); 531 if (rv != PP_OK) 532 return ReportError("FileRef::MakeDirectoryIncludingAncestors", rv); 533 534 // Hang on to a ref to the parent; otherwise the callback will be aborted. 535 pp::FileRef parent_dir_ref = nested_dir_ref.GetParent(); 536 rv = parent_dir_ref.Delete(callback.GetCallback()); 537 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 538 return ReportError("FileRef::Open force_async", rv); 539 if (rv == PP_OK_COMPLETIONPENDING) 540 rv = callback.WaitForResult(); 541 if (rv != PP_ERROR_FAILED) 542 return ReportError("FileRef::Delete", rv); 543 544 pp::FileRef nonexistent_file_ref(file_system, "/nonexistent_file_delete"); 545 rv = nonexistent_file_ref.Delete(callback.GetCallback()); 546 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 547 return ReportError("FileRef::Open force_async", rv); 548 if (rv == PP_OK_COMPLETIONPENDING) 549 rv = callback.WaitForResult(); 550 if (rv != PP_ERROR_FILENOTFOUND) 551 return ReportError("FileRef::Delete", rv); 552 553 // Delete aborted. 554 { 555 pp::FileRef file_ref_abort(file_system, "/file_delete_abort"); 556 pp::FileIO file_io_abort(instance_); 557 rv = file_io_abort.Open(file_ref_abort, PP_FILEOPENFLAG_CREATE, 558 callback.GetCallback()); 559 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 560 return ReportError("FileIO::Open force_async", rv); 561 if (rv == PP_OK_COMPLETIONPENDING) 562 rv = callback.WaitForResult(); 563 if (rv != PP_OK) 564 return ReportError("FileIO::Open", rv); 565 566 callback.reset_run_count(); 567 rv = file_ref_abort.Delete(callback.GetCallback()); 568 } 569 if (callback.run_count() > 0) 570 return "FileRef::Delete ran callback synchronously."; 571 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 572 return ReportError("FileRef::Open force_async", rv); 573 if (rv == PP_OK_COMPLETIONPENDING) { 574 rv = callback.WaitForResult(); 575 if (rv != PP_ERROR_ABORTED) 576 return "FileRef::Delete not aborted."; 577 } else if (rv != PP_OK) { 578 return ReportError("FileRef::Delete", rv); 579 } 580 581 PASS(); 582} 583 584std::string TestFileRef::TestRenameFileAndDirectory() { 585 TestCompletionCallback callback(instance_->pp_instance(), force_async_); 586 pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); 587 int32_t rv = file_system.Open(1024, callback.GetCallback()); 588 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 589 return ReportError("FileSystem::Open force_async", rv); 590 if (rv == PP_OK_COMPLETIONPENDING) 591 rv = callback.WaitForResult(); 592 if (rv != PP_OK) 593 return ReportError("FileSystem::Open", rv); 594 595 pp::FileRef file_ref(file_system, "/file_rename"); 596 pp::FileIO file_io(instance_); 597 rv = file_io.Open(file_ref, PP_FILEOPENFLAG_CREATE, callback.GetCallback()); 598 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 599 return ReportError("FileIO::Open force_async", rv); 600 if (rv == PP_OK_COMPLETIONPENDING) 601 rv = callback.WaitForResult(); 602 if (rv != PP_OK) 603 return ReportError("FileIO::Open", rv); 604 605 pp::FileRef target_file_ref(file_system, "/target_file_rename"); 606 rv = file_ref.Rename(target_file_ref, callback.GetCallback()); 607 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 608 return ReportError("FileRef::Rename force_async", rv); 609 if (rv == PP_OK_COMPLETIONPENDING) 610 rv = callback.WaitForResult(); 611 if (rv != PP_OK) 612 return ReportError("FileRef::Rename", rv); 613 614 pp::FileRef dir_ref(file_system, "/dir_rename"); 615 rv = dir_ref.MakeDirectory(callback.GetCallback()); 616 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 617 return ReportError("FileRef::MakeDirectory force_async", rv); 618 if (rv == PP_OK_COMPLETIONPENDING) 619 rv = callback.WaitForResult(); 620 if (rv != PP_OK) 621 return ReportError("FileRef::MakeDirectory", rv); 622 623 pp::FileRef target_dir_ref(file_system, "/target_dir_rename"); 624 rv = dir_ref.Rename(target_dir_ref, callback.GetCallback()); 625 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 626 return ReportError("FileRef::Rename force_async", rv); 627 if (rv == PP_OK_COMPLETIONPENDING) 628 rv = callback.WaitForResult(); 629 if (rv != PP_OK) 630 return ReportError("FileRef::Rename", rv); 631 632 pp::FileRef nested_dir_ref(file_system, "/dir_rename_1/dir_rename_2"); 633 rv = nested_dir_ref.MakeDirectoryIncludingAncestors(callback.GetCallback()); 634 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 635 return ReportError("FileRef::MakeDirectory force_async", rv); 636 if (rv == PP_OK_COMPLETIONPENDING) 637 rv = callback.WaitForResult(); 638 if (rv != PP_OK) 639 return ReportError("FileRef::MakeDirectoryIncludingAncestors", rv); 640 641 pp::FileRef target_nested_dir_ref(file_system, "/dir_rename_1"); 642 rv = nested_dir_ref.Rename(target_nested_dir_ref, callback.GetCallback()); 643 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 644 return ReportError("FileRef::Open force_async", rv); 645 if (rv == PP_OK_COMPLETIONPENDING) 646 rv = callback.WaitForResult(); 647 if (rv != PP_ERROR_FAILED) 648 return ReportError("FileRef::Rename", rv); 649 650 // Rename aborted. 651 // TODO(viettrungluu): Figure out what we want to do if the target file 652 // resource is destroyed before completion. 653 pp::FileRef target_file_ref_abort(file_system, 654 "/target_file_rename_abort"); 655 { 656 pp::FileRef file_ref_abort(file_system, "/file_rename_abort"); 657 pp::FileIO file_io_abort(instance_); 658 rv = file_io_abort.Open(file_ref_abort, PP_FILEOPENFLAG_CREATE, 659 callback.GetCallback()); 660 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 661 return ReportError("FileIO::Open force_async", rv); 662 if (rv == PP_OK_COMPLETIONPENDING) 663 rv = callback.WaitForResult(); 664 if (rv != PP_OK) 665 return ReportError("FileIO::Open", rv); 666 667 callback.reset_run_count(); 668 rv = file_ref_abort.Rename(target_file_ref_abort, callback.GetCallback()); 669 } 670 if (callback.run_count() > 0) 671 return "FileSystem::Rename ran callback synchronously."; 672 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 673 return ReportError("FileSystem::Rename force_async", rv); 674 if (rv == PP_OK_COMPLETIONPENDING) { 675 rv = callback.WaitForResult(); 676 if (rv != PP_ERROR_ABORTED) 677 return "FileSystem::Rename not aborted."; 678 } else if (rv != PP_OK) { 679 return ReportError("FileSystem::Rename", rv); 680 } 681 682 PASS(); 683} 684 685#ifndef PPAPI_OS_NACL 686std::string TestFileRef::TestFileNameEscaping() { 687 TestCompletionCallback callback(instance_->pp_instance(), force_async_); 688 pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY); 689 int32_t rv = file_system.Open(1024, callback.GetCallback()); 690 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 691 return ReportError("FileSystem::Open force_async", rv); 692 if (rv == PP_OK_COMPLETIONPENDING) 693 rv = callback.WaitForResult(); 694 if (rv != PP_OK) 695 return ReportError("FileSystem::Open", rv); 696 697 std::string test_dir_path = "/dir_for_escaping_test"; 698 // Create a directory in which to test. 699 pp::FileRef test_dir_ref(file_system, test_dir_path.c_str()); 700 rv = test_dir_ref.MakeDirectory(callback.GetCallback()); 701 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 702 return ReportError("FileRef::MakeDirectory force_async", rv); 703 if (rv == PP_OK_COMPLETIONPENDING) 704 rv = callback.WaitForResult(); 705 if (rv != PP_OK) 706 return ReportError("FileRef::MakeDirectory", rv); 707 708 // Create the file with the terrible name. 709 std::string full_file_path = test_dir_path + "/" + kTerribleName; 710 pp::FileRef file_ref(file_system, full_file_path.c_str()); 711 pp::FileIO file_io(instance_); 712 rv = file_io.Open(file_ref, PP_FILEOPENFLAG_CREATE, callback.GetCallback()); 713 if (force_async_ && rv != PP_OK_COMPLETIONPENDING) 714 return ReportError("FileIO::Open force_async", rv); 715 if (rv == PP_OK_COMPLETIONPENDING) 716 rv = callback.WaitForResult(); 717 if (rv != PP_OK) 718 return ReportError("FileIO::Open", rv); 719 720 // DirectoryReader only works out-of-process. 721 if (testing_interface_->IsOutOfProcess()) { 722 TestCompletionCallbackWithOutput< std::vector<pp::DirectoryEntry_Dev> > 723 output_callback(instance_->pp_instance(), force_async_); 724 pp::DirectoryReader_Dev directory_reader(test_dir_ref); 725 726 rv = directory_reader.ReadEntries(output_callback); 727 if (rv == PP_OK_COMPLETIONPENDING) 728 rv = output_callback.WaitForResult(); 729 if (rv != PP_OK && rv != PP_ERROR_FILENOTFOUND) 730 return ReportError("DirectoryEntry_Dev::ReadEntries", rv); 731 732 std::vector<pp::DirectoryEntry_Dev> entries = output_callback.output(); 733 if (entries.empty()) 734 return "Entry was not found."; 735 if (entries.size() != 1) 736 return "Directory had too many entries."; 737 if (entries.front().file_ref().GetName().AsString() != kTerribleName) 738 return "Entry name did not match."; 739 } 740 741 PASS(); 742} 743#endif 744