15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/test_file_io.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <errno.h>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <fcntl.h>
97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <stdio.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <sys/stat.h>
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <sys/types.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/dev/ppb_testing_dev.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_file_io.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/c/private/pp_file_handle.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/trusted/ppb_file_io_trusted.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/file_io.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/file_ref.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/file_system.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/instance.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module.h"
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/cpp/private/file_io_private.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ppapi/cpp/private/pass_file_handle.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/test_utils.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/testing_instance.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(PPAPI_OS_WIN)
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# include <io.h>
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# include <windows.h>
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(hamaji): Use standard windows APIs instead of compatibility layer?
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# define lseek _lseek
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# define read _read
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# define write _write
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# define ssize_t int
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# include <sys/mman.h>
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# include <unistd.h>
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_TEST_CASE(FileIO);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReportMismatch(const std::string& method_name,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const std::string& returned_result,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const std::string& expected_result) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return method_name + " returned '" + returned_result + "'; '" +
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expected_result + "' expected.";
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReportOpenError(int32_t open_flags) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* kFlagNames[] = {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "PP_FILEOPENFLAG_READ",
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "PP_FILEOPENFLAG_WRITE",
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "PP_FILEOPENFLAG_CREATE",
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "PP_FILEOPENFLAG_TRUNCATE",
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "PP_FILEOPENFLAG_EXCLUSIVE"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result = "FileIO:Open had unexpected behavior with flags: ";
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool first_flag = true;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int32_t mask = 1, index = 0; mask <= PP_FILEOPENFLAG_EXCLUSIVE;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       mask <<= 1, ++index) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mask & open_flags) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (first_flag) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        first_flag = false;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result += " | ";
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result += kFlagNames[index];
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (first_flag)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result += "[None]";
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t ReadEntireFile(PP_Instance instance,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       pp::FileIO* file_io,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int32_t offset,
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       std::string* data,
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       CallbackType callback_type) {
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance, callback_type);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[256];
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t read_offset = offset;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;) {
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForResult(
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        file_io->Read(read_offset, buf, sizeof(buf), callback.GetCallback()));
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (callback.result() < 0)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return callback.result();
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (callback.result() == 0)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    read_offset += callback.result();
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    data->append(buf, callback.result());
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_OK;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t ReadToArrayEntireFile(PP_Instance instance,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              pp::FileIO* file_io,
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              int32_t offset,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              std::string* data,
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              CallbackType callback_type) {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestCompletionCallbackWithOutput< std::vector<char> > callback(
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      instance, callback_type);
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (;;) {
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForResult(file_io->Read(offset, 256, callback.GetCallback()));
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int32_t rv = callback.result();
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rv < 0)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return rv;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rv == 0)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<char>& output = callback.output();
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    assert(rv == static_cast<int32_t>(output.size()));
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    offset += rv;
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    data->append(output.begin(), output.end());
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return PP_OK;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
130a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool ReadEntireFileFromFileHandle(int fd, std::string* data) {
131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (lseek(fd, 0, SEEK_SET) < 0)
132a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
133a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  data->clear();
134a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
135a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  int ret;
136a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  do {
137a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    char buf[8192];
138a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ret = read(fd, buf, sizeof(buf));
139a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (ret > 0)
140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      data->append(buf, ret);
141a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  } while (ret > 0);
142a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return ret == 0;
143a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
144a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t WriteEntireBuffer(PP_Instance instance,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          pp::FileIO* file_io,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          int32_t offset,
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const std::string& data,
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          CallbackType callback_type) {
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance, callback_type);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t write_offset = offset;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* buf = data.c_str();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t size = data.size();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (write_offset < offset + size) {
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForResult(file_io->Write(write_offset,
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          &buf[write_offset - offset],
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          size - write_offset + offset,
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          callback.GetCallback()));
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (callback.result() < 0)
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return callback.result();
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (callback.result() == 0)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return PP_ERROR_FAILED;
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    write_offset += callback.result();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_OK;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestFileIO::Init() {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CheckTestingInterface() && EnsureRunningOverHTTP();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestFileIO::RunTests(const std::string& filter) {
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, Open, filter);
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, OpenDirectory, filter);
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, ReadWriteSetLength, filter);
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, ReadToArrayWriteSetLength, filter);
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, TouchQuery, filter);
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, AbortCalls, filter);
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, ParallelReads, filter);
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, ParallelWrites, filter);
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, NotAllowMixedReadWrite, filter);
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, WillWriteWillSetLength, filter);
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, RequestOSFileHandle, filter);
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, RequestOSFileHandleWithOpenExclusive, filter);
189a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  RUN_CALLBACK_TEST(TestFileIO, Mmap, filter);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(viettrungluu): add tests:
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  - that PP_ERROR_PENDING is correctly returned
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  - that operations respect the file open modes (flags)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestFileIO::TestOpen() {
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileRef file_ref(file_system, "/file_open");
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = MatchOpenExpectations(
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &file_system,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_READ,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DONT_CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | DONT_TRUNCATE_IF_EXISTS);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.empty())
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test the behavior of the power set of
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   { PP_FILEOPENFLAG_CREATE,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     PP_FILEOPENFLAG_TRUNCATE,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     PP_FILEOPENFLAG_EXCLUSIVE }.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First of all, none of them are specified.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = MatchOpenExpectations(
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &file_system,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_WRITE,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DONT_CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | DONT_TRUNCATE_IF_EXISTS);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.empty())
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = MatchOpenExpectations(
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &file_system,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | DONT_TRUNCATE_IF_EXISTS);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.empty())
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = MatchOpenExpectations(
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &file_system,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_EXCLUSIVE,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DONT_CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | DONT_TRUNCATE_IF_EXISTS);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.empty())
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = MatchOpenExpectations(
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &file_system,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_TRUNCATE,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DONT_CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | TRUNCATE_IF_EXISTS);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.empty())
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = MatchOpenExpectations(
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &file_system,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE |
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_EXCLUSIVE,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CREATE_IF_DOESNT_EXIST | DONT_OPEN_IF_EXISTS | DONT_TRUNCATE_IF_EXISTS);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.empty())
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = MatchOpenExpectations(
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &file_system,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE | PP_FILEOPENFLAG_TRUNCATE,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | TRUNCATE_IF_EXISTS);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.empty())
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = MatchOpenExpectations(
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &file_system,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_EXCLUSIVE |
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_TRUNCATE,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DONT_CREATE_IF_DOESNT_EXIST | OPEN_IF_EXISTS | TRUNCATE_IF_EXISTS);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.empty())
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = MatchOpenExpectations(
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &file_system,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE |
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_EXCLUSIVE | PP_FILEOPENFLAG_TRUNCATE,
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CREATE_IF_DOESNT_EXIST | DONT_OPEN_IF_EXISTS | DONT_TRUNCATE_IF_EXISTS);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.empty())
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invalid combination: PP_FILEOPENFLAG_TRUNCATE without
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PP_FILEOPENFLAG_WRITE.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = MatchOpenExpectations(
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &file_system,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_TRUNCATE,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      INVALID_FLAG_COMBINATION);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result.empty())
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string TestFileIO::TestOpenDirectory() {
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make a directory.
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pp::FileRef dir_ref(file_system, "/test_dir_open_directory");
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(dir_ref.MakeDirectory(callback.GetCallback()));
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Open the directory. This is expected to fail since directories cannot be
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // opened.
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pp::FileIO file_io(instance_);
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Open(dir_ref, PP_FILEOPENFLAG_READ,
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      callback.GetCallback()));
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_ERROR_NOTAFILE, callback.result());
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PASS();
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestFileIO::TestReadWriteSetLength() {
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileRef file_ref(file_system, "/file_read_write_setlength");
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileIO file_io(instance_);
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Open(file_ref,
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_CREATE |
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_TRUNCATE |
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_READ |
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_WRITE,
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      callback.GetCallback()));
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write something to the file.
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int32_t rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0,
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 "test_test", callback_type());
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Attempt to read a negative number of bytes; it should fail.
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf[256];
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Read(0,
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      buf,
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      -1,
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      callback.GetCallback()));
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_ERROR_FAILED, callback.result());
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read the entire file.
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string read_buffer;
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0, &read_buffer,
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      callback_type());
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("test_test"), read_buffer);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Truncate the file.
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.SetLength(4, callback.GetCallback()));
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check the file contents.
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer.clear();
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0, &read_buffer,
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      callback_type());
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("test"), read_buffer);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to read past the end of the file.
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer.clear();
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = ReadEntireFile(instance_->pp_instance(), &file_io, 100, &read_buffer,
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      callback_type());
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(read_buffer.empty());
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write past the end of the file. The file should be zero-padded.
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 8, "test",
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         callback_type());
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check the contents of the file.
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer.clear();
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0, &read_buffer,
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      callback_type());
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("test\0\0\0\0test", 12), read_buffer);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extend the file.
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.SetLength(16, callback.GetCallback()));
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check the contents of the file.
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer.clear();
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0, &read_buffer,
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      callback_type());
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("test\0\0\0\0test\0\0\0\0", 16), read_buffer);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write in the middle of the file.
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 4, "test",
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         callback_type());
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check the contents of the file.
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer.clear();
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0, &read_buffer,
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      callback_type());
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("testtesttest\0\0\0\0", 16), read_buffer);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read from the middle of the file.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer.clear();
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = ReadEntireFile(instance_->pp_instance(), &file_io, 4, &read_buffer,
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      callback_type());
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("testtest\0\0\0\0", 12), read_buffer);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Append to the end of the file.
4197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  pp::FileIO file_io2(instance_);
4207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  callback.WaitForResult(file_io2.Open(file_ref,
4217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                       PP_FILEOPENFLAG_CREATE |
4227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                       PP_FILEOPENFLAG_READ |
4237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                       PP_FILEOPENFLAG_APPEND,
4247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                       callback.GetCallback()));
4257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  rv = WriteEntireBuffer(instance_->pp_instance(), &file_io2, 0, "appended",
4267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                         callback_type());
4277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
4287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  read_buffer.clear();
4297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  rv = ReadEntireFile(instance_->pp_instance(), &file_io2, 0, &read_buffer,
4307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                      callback_type());
4317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
4327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(std::string("testtesttest\0\0\0\0appended", 24), read_buffer);
4337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is basically a copy of TestReadWriteSetLength, but with the new Read
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// API.  With this test case, we can make sure the two Read's have the same
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// behavior.
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string TestFileIO::TestReadToArrayWriteSetLength() {
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (callback_type() == PP_BLOCKING) {
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // This test does not make sense for blocking callbacks.
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PASS();
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pp::FileRef file_ref(file_system, "/file_read_write_setlength");
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pp::FileIO file_io(instance_);
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Open(file_ref,
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_CREATE |
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_TRUNCATE |
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_READ |
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_WRITE,
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      callback.GetCallback()));
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Write something to the file.
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int32_t rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0,
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 "test_test", callback_type());
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestCompletionCallbackWithOutput< std::vector<char> > callback2(
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      instance_->pp_instance(), callback_type());
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Attempt to read a negative number of bytes; it should fail.
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback2.WaitForResult(file_io.Read(0, -1, callback2.GetCallback()));
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback2);
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_ERROR_FAILED, callback2.result());
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Read the entire file.
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string read_buffer;
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_buffer.reserve(10);
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 0,
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             &read_buffer, callback_type());
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("test_test"), read_buffer);
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Truncate the file.
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.SetLength(4, callback.GetCallback()));
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check the file contents.
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_buffer.clear();
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 0,
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             &read_buffer, callback_type());
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("test"), read_buffer);
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Try to read past the end of the file.
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_buffer.clear();
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 100,
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             &read_buffer, callback_type());
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(read_buffer.empty());
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Write past the end of the file. The file should be zero-padded.
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 8, "test",
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         callback_type());
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check the contents of the file.
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_buffer.clear();
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 0,
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             &read_buffer, callback_type());
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("test\0\0\0\0test", 12), read_buffer);
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Extend the file.
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.SetLength(16, callback.GetCallback()));
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check the contents of the file.
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_buffer.clear();
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 0,
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             &read_buffer, callback_type());
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("test\0\0\0\0test\0\0\0\0", 16), read_buffer);
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Write in the middle of the file.
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 4, "test",
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         callback_type());
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check the contents of the file.
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_buffer.clear();
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 0,
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             &read_buffer, callback_type());
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("testtesttest\0\0\0\0", 16), read_buffer);
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Read from the middle of the file.
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  read_buffer.clear();
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv = ReadToArrayEntireFile(instance_->pp_instance(), &file_io, 4,
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             &read_buffer, callback_type());
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("testtest\0\0\0\0", 12), read_buffer);
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PASS();
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestFileIO::TestTouchQuery() {
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileRef file_ref(file_system, "/file_touch");
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileIO file_io(instance_);
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Open(file_ref,
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_CREATE |
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_TRUNCATE |
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_WRITE,
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      callback.GetCallback()));
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write some data to have a non-zero file size.
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Write(0, "test", 4, callback.GetCallback()));
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(4, callback.result());
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
571a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const PP_Time last_access_time = 123 * 24 * 3600.0;
5724311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // last_modified_time's granularity is 2 seconds
5734311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // NOTE: In NaCl on Windows, NaClDescIO uses _fstat64 to retrieve file info.
5744311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // This function returns strange values for very small time values (near the
5754311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // Unix Epoch). For a value like 246.0, it returns -1. For larger values, it
5764311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // returns values that are exactly an hour less. The value below is handled
5774311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // correctly, and is only 100 days after the start of Unix time.
5784311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  const PP_Time last_modified_time = 100 * 24 * 3600.0;
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Touch(last_access_time, last_modified_time,
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       callback.GetCallback()));
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_FileInfo info;
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Query(&info, callback.GetCallback()));
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((info.size != 4) ||
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (info.type != PP_FILETYPE_REGULAR) ||
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (info.system_type != PP_FILESYSTEMTYPE_LOCALTEMPORARY) ||
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (info.last_access_time != last_access_time) ||
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (info.last_modified_time != last_modified_time))
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "FileIO::Query() has returned bad data.";
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call |Query()| again, to make sure it works a second time.
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Query(&info, callback.GetCallback()));
598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestFileIO::TestAbortCalls() {
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileRef file_ref(file_system, "/file_abort_calls");
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int32_t rv = PP_ERROR_FAILED;
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // First, create a file on which to do ops.
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::FileIO file_io(instance_);
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForResult(
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        file_io.Open(file_ref,
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     PP_FILEOPENFLAG_CREATE | PP_FILEOPENFLAG_WRITE,
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     callback.GetCallback()));
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK_CALLBACK_BEHAVIOR(callback);
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_EQ(PP_OK, callback.result());
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // N.B.: Should write at least 3 bytes.
625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0,
626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           "foobarbazquux", callback_type());
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_EQ(PP_OK, rv);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Abort |Open()|.
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rv = pp::FileIO(instance_)
633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .Open(file_ref, PP_FILEOPENFLAG_READ, callback.GetCallback());
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForAbortResult(rv);
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Abort |Query()|.
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_FileInfo info = { 0 };
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Save a copy and make sure |info| doesn't get written to if it is aborted.
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PP_FileInfo info_copy;
643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    memcpy(&info_copy, &info, sizeof(info));
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::FileIO file_io(instance_);
646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_READ,
647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          callback.GetCallback()));
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CHECK_CALLBACK_BEHAVIOR(callback);
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(PP_OK, callback.result());
650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv = file_io.Query(&info, callback.GetCallback());
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }  // Destroy |file_io|.
653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForResult(rv);
654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK_CALLBACK_BEHAVIOR(callback);
655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (callback_type() == PP_BLOCKING) {
656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(callback.result(), PP_OK);
657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // The operation completed synchronously, so |info| should have changed.
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_NE(0, memcmp(&info_copy, &info, sizeof(info)));
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(callback.result(), PP_ERROR_ABORTED);
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(0, memcmp(&info_copy, &info, sizeof(info)));
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Abort |Touch()|.
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::FileIO file_io(instance_);
669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_WRITE,
670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          callback.GetCallback()));
671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CHECK_CALLBACK_BEHAVIOR(callback);
672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(PP_OK, callback.result());
673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv = file_io.Touch(0, 0, callback.GetCallback());
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }  // Destroy |file_io|.
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForAbortResult(rv);
677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK_CALLBACK_BEHAVIOR(callback);
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Abort |Read()|.
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char buf[3] = { 0 };
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::FileIO file_io(instance_);
685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_READ,
686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          callback.GetCallback()));
687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CHECK_CALLBACK_BEHAVIOR(callback);
688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(PP_OK, callback.result());
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv = file_io.Read(0, buf, sizeof(buf), callback.GetCallback());
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }  // Destroy |file_io|.
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Save a copy to make sure buf isn't written to in the async case.
693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    char buf_copy[3];
694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    memcpy(&buf_copy, &buf, sizeof(buf));
695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForResult(rv);
696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK_CALLBACK_BEHAVIOR(callback);
697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (callback_type() == PP_BLOCKING) {
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(callback.result(), sizeof(buf));
699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(callback.result(), PP_ERROR_ABORTED);
701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(0, memcmp(&buf_copy, &buf, sizeof(buf)));
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Abort |Write()|.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char buf[3] = { 0 };
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::FileIO file_io(instance_);
710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_WRITE,
711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          callback.GetCallback()));
712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CHECK_CALLBACK_BEHAVIOR(callback);
713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(PP_OK, callback.result());
714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv = file_io.Write(0, buf, sizeof(buf), callback.GetCallback());
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }  // Destroy |file_io|.
717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForResult(rv);
718c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK_CALLBACK_BEHAVIOR(callback);
719c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (callback_type() == PP_BLOCKING)
720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(callback.result(), sizeof(buf));
721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else
722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(callback.result(), PP_ERROR_ABORTED);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Abort |SetLength()|.
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::FileIO file_io(instance_);
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_READ,
730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          callback.GetCallback()));
731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CHECK_CALLBACK_BEHAVIOR(callback);
732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(PP_OK, callback.result());
733c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv = file_io.SetLength(3, callback.GetCallback());
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }  // Destroy |file_io|.
736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForAbortResult(rv);
737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK_CALLBACK_BEHAVIOR(callback);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Abort |Flush|.
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::FileIO file_io(instance_);
744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback.WaitForResult(file_io.Open(file_ref, PP_FILEOPENFLAG_WRITE,
745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          callback.GetCallback()));
746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CHECK_CALLBACK_BEHAVIOR(callback);
747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_EQ(PP_OK, callback.result());
748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv = file_io.Flush(callback.GetCallback());
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }  // Destroy |file_io|.
751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForAbortResult(rv);
752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK_CALLBACK_BEHAVIOR(callback);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestFileIO::TestParallelReads() {
759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileRef file_ref(file_system, "/file_parallel_reads");
762c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
763c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileIO file_io(instance_);
767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Open(file_ref,
768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_CREATE |
769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_TRUNCATE |
770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_READ |
771c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_WRITE,
772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      callback.GetCallback()));
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
774c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up testing contents.
777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int32_t rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0,
778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 "abcdefghijkl", callback_type());
779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parallel read operations.
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* border = "__border__";
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int32_t border_size = strlen(border);
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback_1(instance_->pp_instance(), callback_type());
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t read_offset_1 = 0;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t size_1 = 3;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<char> extended_buf_1(border_size * 2 + size_1);
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* buf_1 = &extended_buf_1[border_size];
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(&extended_buf_1[0], border, border_size);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buf_1 + size_1, border, border_size);
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback_2(instance_->pp_instance(), callback_type());
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t read_offset_2 = size_1;
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t size_2 = 9;
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<char> extended_buf_2(border_size * 2 + size_2);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* buf_2 = &extended_buf_2[border_size];
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(&extended_buf_2[0], border, border_size);
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buf_2 + size_2, border, border_size);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t rv_1 = PP_OK;
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t rv_2 = PP_OK;
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (size_1 >= 0 && size_2 >= 0 && size_1 + size_2 > 0) {
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size_1 > 0) {
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv_1 = file_io.Read(read_offset_1, buf_1, size_1,
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          callback_1.GetCallback());
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size_2 > 0) {
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv_2 = file_io.Read(read_offset_2, buf_2, size_2,
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          callback_2.GetCallback());
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size_1 > 0) {
813c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback_1.WaitForResult(rv_1);
814c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CHECK_CALLBACK_BEHAVIOR(callback_1);
815c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_TRUE(callback_1.result() > 0);
816c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      read_offset_1 += callback_1.result();
817c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      buf_1 += callback_1.result();
818c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      size_1 -= callback_1.result();
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size_2 > 0) {
822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback_2.WaitForResult(rv_2);
823c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CHECK_CALLBACK_BEHAVIOR(callback_2);
824c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_TRUE(callback_2.result() > 0);
825c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      read_offset_2 += callback_2.result();
826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      buf_2 += callback_2.result();
827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      size_2 -= callback_2.result();
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
831c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If |size_1| or |size_2| is not 0, we have invoked wrong callback(s).
832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(0, size_1);
833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(0, size_2);
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure every read operation writes into the correct buffer.
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char expected_result_1[] = "__border__abc__border__";
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char expected_result_2[] = "__border__defghijkl__border__";
838c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(strncmp(&extended_buf_1[0], expected_result_1,
839c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      strlen(expected_result_1)) == 0);
840c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(strncmp(&extended_buf_2[0], expected_result_2,
841c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      strlen(expected_result_2)) == 0);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestFileIO::TestParallelWrites() {
846c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileRef file_ref(file_system, "/file_parallel_writes");
849c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
850c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileIO file_io(instance_);
854c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Open(file_ref,
855c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_CREATE |
856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_TRUNCATE |
857c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_READ |
858c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_WRITE,
859c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      callback.GetCallback()));
860c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parallel write operations.
864c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback_1(instance_->pp_instance(), callback_type());
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t write_offset_1 = 0;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* buf_1 = "abc";
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t size_1 = strlen(buf_1);
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
869c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback_2(instance_->pp_instance(), callback_type());
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t write_offset_2 = size_1;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* buf_2 = "defghijkl";
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t size_2 = strlen(buf_2);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t rv_1 = PP_OK;
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t rv_2 = PP_OK;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (size_1 >= 0 && size_2 >= 0 && size_1 + size_2 > 0) {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size_1 > 0) {
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv_1 = file_io.Write(write_offset_1, buf_1, size_1,
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           callback_1.GetCallback());
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size_2 > 0) {
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv_2 = file_io.Write(write_offset_2, buf_2, size_2,
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           callback_2.GetCallback());
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size_1 > 0) {
887c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback_1.WaitForResult(rv_1);
888c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CHECK_CALLBACK_BEHAVIOR(callback_1);
889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_TRUE(callback_1.result() > 0);
890c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      write_offset_1 += callback_1.result();
891c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      buf_1 += callback_1.result();
892c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      size_1 -= callback_1.result();
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size_2 > 0) {
896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback_2.WaitForResult(rv_2);
897c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      CHECK_CALLBACK_BEHAVIOR(callback_2);
898c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ASSERT_TRUE(callback_2.result() > 0);
899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      write_offset_2 += callback_2.result();
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      buf_2 += callback_2.result();
901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      size_2 -= callback_2.result();
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If |size_1| or |size_2| is not 0, we have invoked wrong callback(s).
906c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(0, size_1);
907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(0, size_2);
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check the file contents.
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string read_buffer;
911c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int32_t rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0,
912c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              &read_buffer, callback_type());
913c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("abcdefghijkl"), read_buffer);
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestFileIO::TestNotAllowMixedReadWrite() {
920c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (callback_type() == PP_BLOCKING) {
921c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // This test does not make sense for blocking callbacks.
922c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PASS();
923c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
924c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileRef file_ref(file_system, "/file_not_allow_mixed_read_write");
928c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
929c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
930c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileIO file_io(instance_);
933c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Open(file_ref,
934c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_CREATE |
935c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_TRUNCATE |
936c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_READ |
937c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_WRITE,
938c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      callback.GetCallback()));
939c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
940c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
941c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
942c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback_1(instance_->pp_instance(), PP_REQUIRED);
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t write_offset_1 = 0;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* buf_1 = "mnopqrstuvw";
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t rv_1 = file_io.Write(write_offset_1, buf_1, strlen(buf_1),
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               callback_1.GetCallback());
947c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, rv_1);
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
949c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback_2(instance_->pp_instance(), callback_type());
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t read_offset_2 = 4;
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf_2[3];
952c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback_2.WaitForResult(file_io.Read(read_offset_2, buf_2, sizeof(buf_2),
953c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        callback_2.GetCallback()));
954c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback_2);
955c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_ERROR_INPROGRESS, callback_2.result());
956c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback_1.WaitForResult(rv_1);
957c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback_1);
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cannot query while a write is pending.
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv_1 = file_io.Write(write_offset_1, buf_1, strlen(buf_1),
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       callback_1.GetCallback());
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, rv_1);
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_FileInfo info;
964c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback_2.WaitForResult(file_io.Query(&info, callback_2.GetCallback()));
965c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback_2);
966c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_ERROR_INPROGRESS, callback_2.result());
967c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback_1.WaitForResult(rv_1);
968c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback_1);
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cannot touch while a write is pending.
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv_1 = file_io.Write(write_offset_1, buf_1, strlen(buf_1),
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       callback_1.GetCallback());
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, rv_1);
974c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback_2.WaitForResult(file_io.Touch(1234.0, 5678.0,
975c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           callback_2.GetCallback()));
976c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback_2);
977c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_ERROR_INPROGRESS, callback_2.result());
978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback_1.WaitForResult(rv_1);
979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback_1);
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cannot set length while a write is pending.
9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rv_1 = file_io.Write(write_offset_1, buf_1, strlen(buf_1),
9832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       callback_1.GetCallback());
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(PP_OK_COMPLETIONPENDING, rv_1);
985c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback_2.WaitForResult(file_io.SetLength(123, callback_2.GetCallback()));
986c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback_2);
987c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_ERROR_INPROGRESS, callback_2.result());
988c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback_1.WaitForResult(rv_1);
989c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback_1);
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestFileIO::TestWillWriteWillSetLength() {
995c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileRef file_ref(file_system, "/file_will_write");
999c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
1000c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
1001c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileIO file_io(instance_);
1004c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Open(file_ref,
1005c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_CREATE |
1006c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_TRUNCATE |
1007c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_READ |
1008c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_WRITE,
1009c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      callback.GetCallback()));
1010c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
1011c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PPB_FileIOTrusted* trusted = static_cast<const PPB_FileIOTrusted*>(
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE));
1015c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(trusted);
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get file descriptor. This is only supported in-process for now, so don't
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // test out of process.
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PPB_Testing_Dev* testing_interface = GetTestingInterface();
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (testing_interface && !testing_interface->IsOutOfProcess()) {
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t fd = trusted->GetOSFileDescriptor(file_io.pp_resource());
1022c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(fd >= 0);
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calling WillWrite.
1026c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(trusted->WillWrite(
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file_io.pp_resource(), 0, 9,
1028c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
1029c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
1030c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(9, callback.result());
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Writing the actual data.
1033c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int32_t rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0,
1034c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 "test_test", callback_type());
1035c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string read_buffer;
1038c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0, &read_buffer,
1039c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      callback_type());
1040c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
1041c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("test_test"), read_buffer);
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calling WillSetLength.
1044c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(trusted->WillSetLength(
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file_io.pp_resource(), 4,
1046c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback.GetCallback().pp_completion_callback()));
1047c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
1048c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calling actual SetLength.
1051c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.SetLength(4, callback.GetCallback()));
1052c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
1053c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer.clear();
1056c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rv = ReadEntireFile(instance_->pp_instance(), &file_io, 0, &read_buffer,
1057c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      callback_type());
1058c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, rv);
1059c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(std::string("test"), read_buffer);
1060c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1061c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PASS();
1062c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1063c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1064c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string TestFileIO::TestRequestOSFileHandle() {
1065c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
1066c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1067c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
1068c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pp::FileRef file_ref(file_system, "/file_os_fd");
1069c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1070c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
1071c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
1072c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1073c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  pp::FileIO_Private file_io(instance_);
1074c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(file_io.Open(file_ref,
1075c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_CREATE |
1076c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_TRUNCATE |
1077c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_READ |
1078c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      PP_FILEOPENFLAG_WRITE,
1079c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      callback.GetCallback()));
1080c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
1081c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1082c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallbackWithOutput<pp::PassFileHandle> output_callback(
1083c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      instance_->pp_instance(), callback_type());
1084c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  output_callback.WaitForResult(
1085c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      file_io.RequestOSFileHandle(output_callback.GetCallback()));
1086c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PP_FileHandle handle = output_callback.output().Release();
1087c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(PP_OK, output_callback.result());
1088c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1089c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (handle == PP_kInvalidFileHandle)
1090c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return "FileIO::RequestOSFileHandle() returned a bad file handle.";
1091c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(PPAPI_OS_WIN)
1092c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int fd = _open_osfhandle(reinterpret_cast<intptr_t>(handle),
1093c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           _O_RDWR | _O_BINARY);
1094c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else
1095c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int fd = handle;
1096c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
1097c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (fd < 0)
1098c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return "FileIO::RequestOSFileHandle() returned a bad file descriptor.";
1099c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check write(2) for the native FD.
1101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string msg = "foobar";
1102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ssize_t cnt = write(fd, msg.data(), msg.size());
1103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (cnt < 0)
1104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ReportError("write for native FD returned error", errno);
1105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (cnt != static_cast<ssize_t>(msg.size()))
1106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ReportError("write for native FD count mismatch", cnt);
1107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check lseek(2) for the native FD.
1109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  off_t off = lseek(fd, 0, SEEK_CUR);
1110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (off == static_cast<off_t>(-1))
1111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ReportError("lseek for native FD returned error", errno);
1112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (off != static_cast<off_t>(msg.size()))
1113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ReportError("lseek for native FD offset mismatch", off);
1114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  off = lseek(fd, 0, SEEK_SET);
1116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (off == static_cast<off_t>(-1))
1117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ReportError("lseek for native FD returned error", errno);
1118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (off != 0)
1119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ReportError("lseek for native FD offset mismatch", off);
1120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check read(2) for the native FD.
1122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string buf(msg.size(), '\0');
1123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  cnt = read(fd, &buf[0], msg.size());
1124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (cnt < 0)
1125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ReportError("read for native FD returned error", errno);
1126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (cnt != static_cast<ssize_t>(msg.size()))
1127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ReportError("read for native FD count mismatch", cnt);
1128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (msg != buf)
1129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ReportMismatch("read for native FD", buf, msg);
1130a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  PASS();
1131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
1132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Calling RequestOSFileHandle with the FileIO that is opened with
1134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// PP_FILEOPENFLAG_EXCLUSIVE used to cause NaCl module to crash while loading.
1135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// This is a regression test for crbug.com/243241.
1136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)std::string TestFileIO::TestRequestOSFileHandleWithOpenExclusive() {
1137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
1138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
1140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  pp::FileRef file_ref(file_system, "/file_os_fd2");
1141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
1143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
1144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
11452385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // Open with PP_FILEOPENFLAG_CREATE and PP_FILEOPENFLAG_EXCLUSIVE will fail
11462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  // if the file already exists. Delete it here to make sure it does not.
11472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  callback.WaitForResult(file_ref.Delete(callback.GetCallback()));
11482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  pp::FileIO_Private file_io(instance_);
1150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  callback.WaitForResult(file_io.Open(file_ref,
1151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      PP_FILEOPENFLAG_CREATE |
1152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      PP_FILEOPENFLAG_READ |
1153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      PP_FILEOPENFLAG_WRITE |
1154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      PP_FILEOPENFLAG_EXCLUSIVE,
1155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                      callback.GetCallback()));
1156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
1157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TestCompletionCallbackWithOutput<pp::PassFileHandle> output_callback(
1159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      instance_->pp_instance(), callback_type());
1160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  output_callback.WaitForResult(
1161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      file_io.RequestOSFileHandle(output_callback.GetCallback()));
1162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PP_FileHandle handle = output_callback.output().Release();
1163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (handle == PP_kInvalidFileHandle)
1164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return "FileIO::RequestOSFileHandle() returned a bad file handle.";
1165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(PP_OK, output_callback.result());
1166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PASS();
1168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1170a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)std::string TestFileIO::TestMmap() {
1171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if !defined(PPAPI_OS_WIN)
1172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
1173a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
1175a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  pp::FileRef file_ref(file_system, "/file_os_fd");
1176a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  callback.WaitForResult(file_system.Open(1024, callback.GetCallback()));
1178a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
1179a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1180a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  pp::FileIO_Private file_io(instance_);
1181a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  callback.WaitForResult(file_io.Open(file_ref,
1182a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                      PP_FILEOPENFLAG_CREATE |
1183a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                      PP_FILEOPENFLAG_TRUNCATE |
1184a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                      PP_FILEOPENFLAG_READ |
1185a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                      PP_FILEOPENFLAG_WRITE,
1186a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                      callback.GetCallback()));
1187a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
1188a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1189a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  TestCompletionCallbackWithOutput<pp::PassFileHandle> output_callback(
1190a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      instance_->pp_instance(), callback_type());
1191a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  output_callback.WaitForResult(
1192a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      file_io.RequestOSFileHandle(output_callback.GetCallback()));
1193a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  PP_FileHandle handle = output_callback.output().Release();
1194a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  ASSERT_EQ(PP_OK, output_callback.result());
1195a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1196a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (handle == PP_kInvalidFileHandle)
1197a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return "FileIO::RequestOSFileHandle() returned a bad file handle.";
1198a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  int fd = handle;
1199a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (fd < 0)
1200a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return "FileIO::RequestOSFileHandle() returned a bad file descriptor.";
1201a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1202a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Check write(2) for the native FD.
1203a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const std::string msg = "foobar";
1204a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  ssize_t cnt = write(fd, msg.data(), msg.size());
1205a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (cnt < 0)
1206a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return ReportError("write for native FD returned error", errno);
1207a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (cnt != static_cast<ssize_t>(msg.size()))
1208a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return ReportError("write for native FD count mismatch", cnt);
1209a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1210a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // BEGIN mmap(2) test with a file handle opened in READ-WRITE mode.
1211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check mmap(2) for read.
1212a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  {
1213a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    char* mapped = reinterpret_cast<char*>(
1214a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        mmap(NULL, msg.size(), PROT_READ, MAP_PRIVATE, fd, 0));
1215a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (mapped == MAP_FAILED)
1216a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportError("mmap(r) for native FD returned errno", errno);
1217a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Make sure the buffer is cleared.
1218a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    std::string buf = std::string(msg.size(), '\0');
1219a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    memcpy(&buf[0], mapped, msg.size());
1220a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (msg != buf)
1221a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportMismatch("mmap(r) for native FD", buf, msg);
1222a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int r = munmap(mapped, msg.size());
1223a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (r < 0)
1224a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportError("munmap for native FD returned error", errno);
1225a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
1226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1227a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Check mmap(2) for write with MAP_PRIVATE
1228a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  {
1229a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    char* mapped = reinterpret_cast<char*>(
1230a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        mmap(NULL, msg.size(), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0));
1231a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (mapped == MAP_FAILED)
1232a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportError("mmap(r) for native FD returned errno", errno);
1233a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Make sure the file is not polluted by writing to privage mmap.
1234a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    strncpy(mapped, "baz", 3);
1235a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    std::string read_buffer;
1236a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ASSERT_TRUE(ReadEntireFileFromFileHandle(fd, &read_buffer));
1237a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (msg != read_buffer)
1238a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportMismatch("file content != msg", read_buffer, msg);
1239a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int r = munmap(mapped, msg.size());
1240a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (r < 0)
1241a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportError("munmap for native FD returned error", errno);
1242a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
1243a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1244a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Check mmap(2) for write with MAP_SHARED.
1245a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  {
1246a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    char* mapped = reinterpret_cast<char*>(
1247a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        mmap(NULL, msg.size(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
1248a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (mapped == MAP_FAILED)
1249a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportError("mmap(w) for native FD returned errno", errno);
1250a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // s/foo/baz/
1251a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    strncpy(mapped, "baz", 3);
1252a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    std::string read_buffer;
1253a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ASSERT_TRUE(ReadEntireFileFromFileHandle(fd, &read_buffer));
1254a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (read_buffer != "bazbar")
1255a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportMismatch("file content != msg", read_buffer, "bazbar");
1256a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int r = munmap(mapped, msg.size());
1257a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (r < 0)
1258a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportError("munmap for native FD returned error", errno);
1259a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
1260a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // END mmap(2) test with a file handle opened in READ-WRITE mode.
1261a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1262a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (close(fd) < 0)
1263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ReportError("close for native FD returned error", errno);
1264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1265a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // BEGIN mmap(2) test with a file handle opened in READONLY mode.
1266a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  file_io = pp::FileIO_Private(instance_);
1267a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  callback.WaitForResult(file_io.Open(file_ref,
1268a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                      PP_FILEOPENFLAG_READ,
1269a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                      callback.GetCallback()));
1270a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
1271a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1272a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  output_callback = TestCompletionCallbackWithOutput<pp::PassFileHandle>(
1273a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      instance_->pp_instance(), callback_type());
1274a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  output_callback.WaitForResult(
1275a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      file_io.RequestOSFileHandle(output_callback.GetCallback()));
1276a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  handle = output_callback.output().Release();
1277a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  ASSERT_EQ(PP_OK, output_callback.result());
1278a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1279a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (handle == PP_kInvalidFileHandle)
1280a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return "FileIO::RequestOSFileHandle() returned a bad file handle.";
1281a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  fd = handle;
1282a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (fd < 0)
1283a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return "FileIO::RequestOSFileHandle() returned a bad file descriptor.";
1284a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1285a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const std::string msg2 = "bazbar";
1286a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1287a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Check mmap(2) for read.
1288a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  {
1289a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    char* mapped = reinterpret_cast<char*>(
1290a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        mmap(NULL, msg2.size(), PROT_READ, MAP_PRIVATE, fd, 0));
1291a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (mapped == MAP_FAILED)
1292a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportError("mmap(r) for native FD returned errno", errno);
1293a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Make sure the buffer is cleared.
1294a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    std::string buf = std::string(msg2.size(), '\0');
1295a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    memcpy(&buf[0], mapped, msg2.size());
1296a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (msg2 != buf)
1297a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportMismatch("mmap(r) for native FD", buf, msg2);
1298a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int r = munmap(mapped, msg2.size());
1299a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (r < 0)
1300a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportError("munmap for native FD returned error", errno);
1301a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
1302a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1303a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Check mmap(2) for write with MAP_PRIVATE
1304a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  {
1305a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    char* mapped = reinterpret_cast<char*>(
1306a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        mmap(NULL, msg2.size(), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0));
1307a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (mapped == MAP_FAILED)
1308a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportError("mmap(r) for native FD returned errno", errno);
1309a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Make sure the file is not polluted by writing to privage mmap.
1310a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    strncpy(mapped, "baz", 3);
1311a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    std::string read_buffer;
1312a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ASSERT_TRUE(ReadEntireFileFromFileHandle(fd, &read_buffer));
1313a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (msg2 != read_buffer)
1314a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportMismatch("file content != msg2", read_buffer, msg2);
1315a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    int r = munmap(mapped, msg2.size());
1316a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (r < 0)
1317a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportError("munmap for native FD returned error", errno);
1318a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
1319a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1320a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Check mmap(2) for write with MAP_SHARED.
1321a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  {
1322a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    char* mapped = reinterpret_cast<char*>(
1323a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        mmap(NULL, msg2.size(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
1324a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (mapped != MAP_FAILED)
1325a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      return ReportError("mmap(w) for native FD must fail when opened readonly",
1326a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                         -1);
1327a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
1328a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // END mmap(2) test with a file handle opened in READONLY mode.
1329a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1330a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (close(fd) < 0)
1331a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return ReportError("close for native FD returned error", errno);
1332a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif  // !defined(PPAPI_OS_WIN)
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PASS();
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string TestFileIO::MatchOpenExpectations(pp::FileSystem* file_system,
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              size_t open_flags,
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              size_t expectations) {
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string bad_argument =
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "TestFileIO::MatchOpenExpectations has invalid input arguments.";
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool invalid_combination = !!(expectations & INVALID_FLAG_COMBINATION);
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (invalid_combination) {
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expectations != INVALID_FLAG_COMBINATION)
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return bad_argument;
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Validate that one and only one of <some_expectation> and
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // DONT_<some_expectation> is specified.
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t remains = expectations, end = END_OF_OPEN_EXPECATION_PAIRS;
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         end != 0; remains >>= 2, end >>= 2) {
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!!(remains & 1) == !!(remains & 2))
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return bad_argument;
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool create_if_doesnt_exist = !!(expectations & CREATE_IF_DOESNT_EXIST);
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool open_if_exists = !!(expectations & OPEN_IF_EXISTS);
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool truncate_if_exists = !!(expectations & TRUNCATE_IF_EXISTS);
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileRef existent_file_ref(
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *file_system, "/match_open_expectation_existent_non_empty_file");
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileRef nonexistent_file_ref(
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *file_system, "/match_open_expectation_nonexistent_file");
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup files for test.
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForResult(existent_file_ref.Delete(callback.GetCallback()));
1368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK_CALLBACK_BEHAVIOR(callback);
1369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(callback.result() == PP_OK ||
1370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                callback.result() == PP_ERROR_FILENOTFOUND);
1371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForResult(nonexistent_file_ref.Delete(callback.GetCallback()));
1372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK_CALLBACK_BEHAVIOR(callback);
1373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(callback.result() == PP_OK ||
1374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                callback.result() == PP_ERROR_FILENOTFOUND);
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::FileIO existent_file_io(instance_);
1377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForResult(existent_file_io.Open(
1378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        existent_file_ref,
1379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        PP_FILEOPENFLAG_CREATE | PP_FILEOPENFLAG_WRITE,
1380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        callback.GetCallback()));
1381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK_CALLBACK_BEHAVIOR(callback);
1382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_EQ(PP_OK, callback.result());
1383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int32_t rv = WriteEntireBuffer(instance_->pp_instance(), &existent_file_io,
1384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   0, "foobar", callback_type());
1385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_EQ(PP_OK, rv);
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileIO existent_file_io(instance_);
1389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(existent_file_io.Open(existent_file_ref, open_flags,
1390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               callback.GetCallback()));
1391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
1392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if ((invalid_combination && callback.result() == PP_OK) ||
1393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      (!invalid_combination &&
1394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       ((callback.result() == PP_OK) != open_if_exists))) {
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ReportOpenError(open_flags);
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!invalid_combination && open_if_exists) {
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_FileInfo info;
1400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.WaitForResult(existent_file_io.Query(&info,
1401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                  callback.GetCallback()));
1402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK_CALLBACK_BEHAVIOR(callback);
1403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_EQ(PP_OK, callback.result());
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (truncate_if_exists != (info.size == 0))
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ReportOpenError(open_flags);
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp::FileIO nonexistent_file_io(instance_);
1409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.WaitForResult(nonexistent_file_io.Open(nonexistent_file_ref,
1410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                  open_flags,
1411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                  callback.GetCallback()));
1412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
1413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if ((invalid_combination && callback.result() == PP_OK) ||
1414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      (!invalid_combination &&
1415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       ((callback.result() == PP_OK) != create_if_doesnt_exist))) {
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ReportOpenError(open_flags);
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string();
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(viettrungluu): Test Close(). crbug.com/69457
1423