15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file.
43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <errno.h>
63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <fcntl.h>
768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <set>
968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <string>
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <gmock/gmock.h>
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <ppapi/c/ppb_file_io.h>
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <ppapi/c/pp_directory_entry.h>
143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <ppapi/c/pp_errors.h>
153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <ppapi/c/pp_instance.h>
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(WIN32)
173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <windows.h>  // For Sleep()
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "fake_ppapi/fake_pepper_interface_html5_fs.h"
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "nacl_io/kernel_handle.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/html5fs/html5_fs.h"
233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/osdirent.h"
243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/osunistd.h"
253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "nacl_io/pepper_interface_delegate.h"
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "sdk_util/scoped_ref.h"
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "mock_util.h"
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "pepper_interface_mock.h"
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using namespace nacl_io;
313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using namespace sdk_util;
323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using ::testing::_;
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using ::testing::DoAll;
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using ::testing::Invoke;
363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using ::testing::Mock;
373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using ::testing::Return;
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace {
403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Html5FsForTesting : public Html5Fs {
423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public:
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Html5FsForTesting(StringMap_t& string_map, PepperInterface* ppapi,
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    int expected_error = 0) {
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FsInitArgs args;
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    args.string_map = string_map;
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    args.ppapi = ppapi;
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Error error = Init(args);
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_EQ(expected_error, error);
503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool Exists(const char* filename) {
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ScopedNode node;
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (Open(Path(filename), O_RDONLY, &node))
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    struct stat buf;
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return node->GetStat(&buf) == 0;
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Html5FsTest : public ::testing::Test {
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) public:
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Html5FsTest();
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) protected:
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FakePepperInterfaceHtml5Fs ppapi_html5_;
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PepperInterfaceMock ppapi_mock_;
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PepperInterfaceDelegate ppapi_;
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)};
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Html5FsTest::Html5FsTest()
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : ppapi_mock_(ppapi_html5_.GetInstance()),
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ppapi_(ppapi_html5_.GetInstance()) {
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Default delegation to the html5 pepper interface.
763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ppapi_.SetCoreInterfaceDelegate(ppapi_html5_.GetCoreInterface());
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ppapi_.SetFileSystemInterfaceDelegate(ppapi_html5_.GetFileSystemInterface());
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ppapi_.SetFileRefInterfaceDelegate(ppapi_html5_.GetFileRefInterface());
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ppapi_.SetFileIoInterfaceDelegate(ppapi_html5_.GetFileIoInterface());
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ppapi_.SetVarInterfaceDelegate(ppapi_html5_.GetVarInterface());
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}  // namespace
843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(Html5FsTest, FilesystemType) {
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const char* filesystem_type_strings[] = {"", "PERSISTENT", "TEMPORARY", NULL};
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  PP_FileSystemType filesystem_type_values[] = {
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      PP_FILESYSTEMTYPE_LOCALPERSISTENT,  // Default to persistent.
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      PP_FILESYSTEMTYPE_LOCALPERSISTENT, PP_FILESYSTEMTYPE_LOCALTEMPORARY};
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const char* expected_size_strings[] = {"100", "12345", NULL};
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const int expected_size_values[] = {100, 12345};
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FileSystemInterfaceMock* filesystem_mock =
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ppapi_mock_.GetFileSystemInterface();
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FakeFileSystemInterface* filesystem_fake =
983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      static_cast<FakeFileSystemInterface*>(
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          ppapi_html5_.GetFileSystemInterface());
1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (int i = 0; filesystem_type_strings[i] != NULL; ++i) {
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const char* filesystem_type_string = filesystem_type_strings[i];
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    PP_FileSystemType expected_filesystem_type = filesystem_type_values[i];
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    for (int j = 0; expected_size_strings[j] != NULL; ++j) {
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      const char* expected_size_string = expected_size_strings[j];
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      int64_t expected_expected_size = expected_size_values[j];
1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ppapi_.SetFileSystemInterfaceDelegate(filesystem_mock);
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ON_CALL(*filesystem_mock, Create(_, _)).WillByDefault(
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          Invoke(filesystem_fake, &FakeFileSystemInterface::Create));
1133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      EXPECT_CALL(*filesystem_mock,
1153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                  Create(ppapi_.GetInstance(), expected_filesystem_type));
1163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      EXPECT_CALL(*filesystem_mock, Open(_, expected_expected_size, _))
1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)          .WillOnce(DoAll(CallCallback<2>(int32_t(PP_OK)),
1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                          Return(int32_t(PP_OK_COMPLETIONPENDING))));
1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      StringMap_t map;
1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      map["type"] = filesystem_type_string;
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      map["expected_size"] = expected_size_string;
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      Mock::VerifyAndClearExpectations(&filesystem_mock);
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
1283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(Html5FsTest, PassFilesystemResource) {
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fail if given a bad resource.
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  {
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    StringMap_t map;
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    map["filesystem_resource"] = "0";
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ScopedRef<Html5FsForTesting> fs(
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        new Html5FsForTesting(map, &ppapi_, EINVAL));
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  {
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_TRUE(ppapi_html5_.filesystem_template()->AddEmptyFile("/foo", NULL));
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PP_Resource filesystem = ppapi_html5_.GetFileSystemInterface()->Create(
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ppapi_html5_.GetInstance(), PP_FILESYSTEMTYPE_LOCALPERSISTENT);
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ASSERT_EQ(int32_t(PP_OK), ppapi_html5_.GetFileSystemInterface()->Open(
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              filesystem, 0, PP_BlockUntilComplete()));
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    StringMap_t map;
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    char buffer[30];
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    snprintf(buffer, 30, "%d", filesystem);
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    map["filesystem_resource"] = buffer;
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ScopedRef<Html5FsForTesting> fs(
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        new Html5FsForTesting(map, &ppapi_));
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ASSERT_TRUE(fs->Exists("/foo"));
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ppapi_html5_.GetCoreInterface()->ReleaseResource(filesystem);
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(Html5FsTest, MountSubtree) {
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(ppapi_html5_.filesystem_template()->AddEmptyFile("/foo/bar",
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                               NULL));
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  StringMap_t map;
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  map["SOURCE"] = "/foo";
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_TRUE(fs->Exists("/bar"));
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_FALSE(fs->Exists("/foo/bar"));
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(Html5FsTest, Mkdir) {
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t map;
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // mkdir at the root should return EEXIST, not EACCES.
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(EEXIST, fs->Mkdir(Path("/"), 0644));
1783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  Path path("/foo");
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_FALSE(fs->Exists("/foo"));
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Mkdir(path, 0644));
1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  struct stat stat;
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(path, O_RDONLY, &node));
1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, node->GetStat(&stat));
1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(S_IFDIR, stat.st_mode & S_IFDIR);
1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(Html5FsTest, Remove) {
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const char* kPath = "/foo";
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(ppapi_html5_.filesystem_template()->AddEmptyFile(kPath, NULL));
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t map;
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
1963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Path path(kPath);
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_TRUE(fs->Exists(kPath));
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Remove(path));
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(fs->Exists(kPath));
2013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(Html5FsTest, Unlink) {
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(ppapi_html5_.filesystem_template()->AddEmptyFile("/file", NULL));
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(ppapi_html5_.filesystem_template()->AddDirectory("/dir", NULL));
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t map;
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_TRUE(fs->Exists("/dir"));
2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_TRUE(fs->Exists("/file"));
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_EQ(0, fs->Unlink(Path("/file")));
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(EISDIR, fs->Unlink(Path("/dir")));
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(fs->Exists("/file"));
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(fs->Exists("/dir"));
2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(Html5FsTest, Rmdir) {
2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(ppapi_html5_.filesystem_template()->AddEmptyFile("/file", NULL));
2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(ppapi_html5_.filesystem_template()->AddDirectory("/dir", NULL));
2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t map;
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
2243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(ENOTDIR, fs->Rmdir(Path("/file")));
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, fs->Rmdir(Path("/dir")));
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(fs->Exists("/dir"));
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(fs->Exists("/file"));
2293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(Html5FsTest, Rename) {
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(ppapi_html5_.filesystem_template()->AddEmptyFile("/foo", NULL));
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StringMap_t map;
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_TRUE(fs->Exists("/foo"));
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_EQ(0, fs->Rename(Path("/foo"), Path("/bar")));
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(fs->Exists("/foo"));
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(fs->Exists("/bar"));
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(Html5FsTest, OpenForCreate) {
2443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t map;
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(fs->Exists("/foo"));
2483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Path path("/foo");
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(path, O_CREAT | O_RDWR, &node));
2523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Write some data.
2543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  char contents[] = "contents";
2553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int bytes_written = 0;
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(0, node->Write(HandleAttr(), &contents[0], strlen(contents),
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           &bytes_written));
2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(strlen(contents), bytes_written);
2593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Create again.
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(path, O_CREAT, &node));
2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Check that the file still has data.
264010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  off_t size;
2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, node->GetSize(&size));
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(strlen(contents), size);
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Open exclusively.
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(EEXIST, fs->Open(path, O_CREAT | O_EXCL, &node));
2703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Try to truncate without write access.
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(EINVAL, fs->Open(path, O_CREAT | O_TRUNC, &node));
2733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Open and truncate.
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(path, O_CREAT | O_TRUNC | O_WRONLY, &node));
2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // File should be empty.
2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, node->GetSize(&size));
2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, size);
2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(Html5FsTest, Read) {
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const char contents[] = "contents";
2848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_TRUE(
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ppapi_html5_.filesystem_template()->AddFile("/file", contents, NULL));
2868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_TRUE(ppapi_html5_.filesystem_template()->AddDirectory("/dir", NULL));
2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t map;
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(Path("/file"), O_RDONLY, &node));
2923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  char buffer[10] = {0};
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int bytes_read = 0;
2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  HandleAttr attr;
2968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
2978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(strlen(contents), bytes_read);
2988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_STREQ(contents, buffer);
2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Read nothing past the end of the file.
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  attr.offs = 100;
3028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
3038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0, bytes_read);
3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Read part of the data.
3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  attr.offs = 4;
3078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_EQ(strlen(contents) - 4, bytes_read);
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  buffer[bytes_read] = 0;
3108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_STREQ("ents", buffer);
3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Writing should fail.
3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int bytes_written = 1;  // Set to a non-zero value.
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  attr.offs = 0;
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(EACCES,
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            node->Write(attr, &buffer[0], sizeof(buffer), &bytes_written));
3178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0, bytes_written);
3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Reading from a directory should fail.
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(Path("/dir"), O_RDONLY, &node));
3218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(EISDIR, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(Html5FsTest, Write) {
3253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const char contents[] = "contents";
3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(
3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ppapi_html5_.filesystem_template()->AddFile("/file", contents, NULL));
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(ppapi_html5_.filesystem_template()->AddDirectory("/dir", NULL));
3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t map;
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
3323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(Path("/file"), O_WRONLY, &node));
3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Reading should fail.
3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  char buffer[10];
3383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int bytes_read = 1;  // Set to a non-zero value.
3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  HandleAttr attr;
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(EACCES, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, bytes_read);
3423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Reopen as read-write.
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(Path("/file"), O_RDWR, &node));
3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int bytes_written = 1;  // Set to a non-zero value.
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  attr.offs = 3;
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(0, node->Write(attr, "struct", 6, &bytes_written));
3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(6, bytes_written);
3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  attr.offs = 0;
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(9, bytes_read);
3543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  buffer[bytes_read] = 0;
3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_STREQ("construct", buffer);
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Writing to a directory should fail.
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, fs->Open(Path("/dir"), O_RDWR, &node));
3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(EISDIR, node->Write(attr, &buffer[0], sizeof(buffer), &bytes_read));
3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(Html5FsTest, GetStat) {
3633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const int creation_time = 1000;
3643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const int access_time = 2000;
3653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const int modified_time = 3000;
3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const char contents[] = "contents";
3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Create fake file.
3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  FakeHtml5FsNode* fake_node;
3703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(ppapi_html5_.filesystem_template()->AddFile(
3713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "/file", contents, &fake_node));
3723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  fake_node->set_creation_time(creation_time);
3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  fake_node->set_last_access_time(access_time);
3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  fake_node->set_last_modified_time(modified_time);
3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Create fake directory.
3773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(
3783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ppapi_html5_.filesystem_template()->AddDirectory("/dir", &fake_node));
3793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  fake_node->set_creation_time(creation_time);
3803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  fake_node->set_last_access_time(access_time);
3813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  fake_node->set_last_modified_time(modified_time);
3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t map;
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
3853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(Path("/file"), O_RDONLY, &node));
3883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  struct stat statbuf;
3903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, node->GetStat(&statbuf));
3918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  EXPECT_EQ(S_IFREG, statbuf.st_mode & S_IFMT);
3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(S_IRALL | S_IWALL | S_IXALL, statbuf.st_mode & ~S_IFMT);
3933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(strlen(contents), statbuf.st_size);
3943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(access_time, statbuf.st_atime);
3953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(creation_time, statbuf.st_ctime);
3963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(modified_time, statbuf.st_mtime);
3973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Test Get* and Isa* methods.
399010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  off_t size;
4003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, node->GetSize(&size));
4013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(strlen(contents), size);
4023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_FALSE(node->IsaDir());
4033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(node->IsaFile());
404effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_EQ(ENOTTY, node->Isatty());
4053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // GetStat on a directory...
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, fs->Open(Path("/dir"), O_RDONLY, &node));
4083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, node->GetStat(&statbuf));
4098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  EXPECT_EQ(S_IFDIR, statbuf.st_mode & S_IFMT);
4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(S_IRALL | S_IWALL | S_IXALL, statbuf.st_mode & ~S_IFMT);
4113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, statbuf.st_size);
4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(access_time, statbuf.st_atime);
4133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(creation_time, statbuf.st_ctime);
4143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(modified_time, statbuf.st_mtime);
4153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Test Get* and Isa* methods.
4173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, node->GetSize(&size));
4183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, size);
4193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(node->IsaDir());
4203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_FALSE(node->IsaFile());
421effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_EQ(ENOTTY, node->Isatty());
4223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(Html5FsTest, FTruncate) {
4253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const char contents[] = "contents";
4263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(
4273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ppapi_html5_.filesystem_template()->AddFile("/file", contents, NULL));
4283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(ppapi_html5_.filesystem_template()->AddDirectory("/dir", NULL));
4293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t map;
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
4323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(Path("/file"), O_RDWR, &node));
4353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  HandleAttr attr;
4373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  char buffer[10] = {0};
4383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int bytes_read = 0;
4393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // First make the file shorter...
4413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, node->FTruncate(4));
4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(4, bytes_read);
4443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  buffer[bytes_read] = 0;
4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_STREQ("cont", buffer);
4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Now make the file longer...
4483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, node->FTruncate(8));
4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(0, node->Read(attr, &buffer[0], sizeof(buffer), &bytes_read));
4503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(8, bytes_read);
4513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  buffer[bytes_read] = 0;
4523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_STREQ("cont\0\0\0\0", buffer);
4533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Ftruncate should fail for a directory.
4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(0, fs->Open(Path("/dir"), O_RDONLY, &node));
4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(EISDIR, node->FTruncate(4));
4573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(Html5FsTest, GetDents) {
4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const char contents[] = "contents";
4613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(
4623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      ppapi_html5_.filesystem_template()->AddFile("/file", contents, NULL));
4633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  StringMap_t map;
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedRef<Html5FsForTesting> fs(new Html5FsForTesting(map, &ppapi_));
4663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode root;
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(Path("/"), O_RDONLY, &root));
4693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode node;
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(Path("/file"), O_RDWR, &node));
4723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  struct stat stat;
4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_EQ(0, node->GetStat(&stat));
4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ino_t file1_ino = stat.st_ino;
4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Should fail for regular files.
47868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const size_t kMaxDirents = 5;
47968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  dirent dirents[kMaxDirents];
4803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int bytes_read = 1;  // Set to a non-zero value.
4813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  memset(&dirents[0], 0, sizeof(dirents));
4833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(ENOTDIR,
4843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            node->GetDents(0, &dirents[0], sizeof(dirents), &bytes_read));
4853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, bytes_read);
4863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Should work with root directory.
4883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // +2 to test a size that is not a multiple of sizeof(dirent).
4893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Expect it to round down.
4903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  memset(&dirents[0], 0, sizeof(dirents));
49168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_EQ(
49268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      0, root->GetDents(0, &dirents[0], sizeof(dirent) * 3 + 2, &bytes_read));
49368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
49468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  {
49568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    size_t num_dirents = bytes_read / sizeof(dirent);
49668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(3, num_dirents);
49768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(sizeof(dirent) * num_dirents, bytes_read);
49868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
49968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    std::multiset<std::string> dirnames;
500f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (size_t i = 0; i < num_dirents; ++i) {
50168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EXPECT_EQ(sizeof(dirent), dirents[i].d_off);
50268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EXPECT_EQ(sizeof(dirent), dirents[i].d_reclen);
50368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      dirnames.insert(dirents[i].d_name);
50468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
50568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
50668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(1, dirnames.count("file"));
50768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(1, dirnames.count("."));
50868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(1, dirnames.count(".."));
50968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
5103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Add another file...
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(0, fs->Open(Path("/file2"), O_CREAT, &node));
5131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_EQ(0, node->GetStat(&stat));
5141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ino_t file2_ino = stat.st_ino;
5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // These files SHOULD not hash to the same value but COULD.
5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_NE(file1_ino, file2_ino);
5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Read the root directory again.
5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  memset(&dirents[0], 0, sizeof(dirents));
5213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, root->GetDents(0, &dirents[0], sizeof(dirents), &bytes_read));
52268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
52368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  {
52468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    size_t num_dirents = bytes_read / sizeof(dirent);
52568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(4, num_dirents);
52668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(sizeof(dirent) * num_dirents, bytes_read);
52768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
52868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    std::multiset<std::string> dirnames;
529f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (size_t i = 0; i < num_dirents; ++i) {
53068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EXPECT_EQ(sizeof(dirent), dirents[i].d_off);
53168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EXPECT_EQ(sizeof(dirent), dirents[i].d_reclen);
53268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      dirnames.insert(dirents[i].d_name);
5331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (!strcmp(dirents[i].d_name, "file")) {
5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        EXPECT_EQ(dirents[i].d_ino, file1_ino);
5361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
5371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (!strcmp(dirents[i].d_name, "file2")) {
5381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        EXPECT_EQ(dirents[i].d_ino, file2_ino);
5391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
54068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
54168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
54268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(1, dirnames.count("file"));
54368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(1, dirnames.count("file2"));
54468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(1, dirnames.count("."));
54568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(1, dirnames.count(".."));
5463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
548