15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <set>
968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <string>
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "gtest/gtest.h"
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/devfs/dev_fs.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/dir_node.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "nacl_io/error.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "nacl_io/ioctl.h"
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "nacl_io/kernel_handle.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/kernel_proxy.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/memfs/mem_fs.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/memfs/mem_fs_node.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/node.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osdirent.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define NULL_NODE ((Node*)NULL)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochusing namespace nacl_io;
27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int s_alloc_num = 0;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MemFsForTesting : public MemFs {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MemFsForTesting() {
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    FsInitArgs args(1);
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(0, Init(args));
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool Exists(const char* filename) {
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ScopedNode node;
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (Open(Path(filename), O_RDONLY, &node))
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    struct stat buf;
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return node->GetStat(&buf) == 0;
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int num_nodes() { return inode_pool_.size(); }
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MemFsNodeForTesting : public MemFsNode {
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MemFsNodeForTesting() : MemFsNode(NULL) { s_alloc_num++; }
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ~MemFsNodeForTesting() { s_alloc_num--; }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  using MemFsNode::Init;
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  using MemFsNode::AddChild;
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  using MemFsNode::RemoveChild;
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  using MemFsNode::FindChild;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class DirNodeForTesting : public DirNode {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DirNodeForTesting() : DirNode(NULL) { s_alloc_num++; }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ~DirNodeForTesting() { s_alloc_num--; }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  using DirNode::Init;
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  using DirNode::AddChild;
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  using DirNode::RemoveChild;
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  using DirNode::FindChild;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MemFsNodeTest, File) {
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MemFsNodeForTesting file;
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode result_node;
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  off_t result_size = 0;
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result_bytes = 0;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  EXPECT_EQ(0, file.Init(0));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test properties
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, file.GetLinks());
878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  EXPECT_EQ(S_IRALL | S_IWALL, file.GetMode());
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(S_IFREG, file.GetType());
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_FALSE(file.IsaDir());
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(file.IsaFile());
91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_EQ(ENOTTY, file.Isatty());
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, file.RefCount());
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test IO
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf1[1024];
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf2[1024 * 2];
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t a = 0; a < sizeof(buf1); a++)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buf1[a] = a;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(buf2, 0, sizeof(buf2));
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  HandleAttr attr;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, file.GetSize(&result_size));
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(0, result_size);
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(0, file.Read(attr, buf2, sizeof(buf2), &result_bytes));
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(0, result_bytes);
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, file.GetSize(&result_size));
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(0, result_size);
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(0, file.Write(attr, buf1, sizeof(buf1), &result_bytes));
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(sizeof(buf1), result_bytes);
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, file.GetSize(&result_size));
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(sizeof(buf1), result_size);
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(0, file.Read(attr, buf2, sizeof(buf2), &result_bytes));
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(sizeof(buf1), result_bytes);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, memcmp(buf1, buf2, sizeof(buf1)));
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct stat s;
1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, file.GetStat(&s));
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_LT(0, s.st_ino);  // 0 is an invalid inode number.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(sizeof(buf1), s.st_size);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Directory operations should fail
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct dirent d;
1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(ENOTDIR, file.GetDents(0, &d, sizeof(d), &result_bytes));
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(ENOTDIR, file.AddChild("", result_node));
1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(ENOTDIR, file.RemoveChild(""));
1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(ENOTDIR, file.FindChild("", &result_node));
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL_NODE, result_node.get());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST(MemFsNodeTest, Fchmod) {
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MemFsNodeForTesting file;
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_EQ(0, file.Init(0));
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(S_IRALL | S_IWALL, file.GetMode());
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  struct stat s;
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_EQ(0, file.GetStat(&s));
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(S_IFREG | S_IRALL | S_IWALL, s.st_mode);
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Change to read-only.
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(0, file.Fchmod(S_IRALL));
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(S_IRALL, file.GetMode());
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ASSERT_EQ(0, file.GetStat(&s));
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(S_IFREG | S_IRALL, s.st_mode);
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MemFsNodeTest, FTruncate) {
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MemFsNodeForTesting file;
151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  off_t result_size = 0;
152424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int result_bytes = 0;
153424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
154424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  char data[1024];
155424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  char buffer[1024];
156424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  char zero[1024];
157424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
158424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  for (size_t a = 0; a < sizeof(data); a++)
159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    data[a] = a;
160424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  memset(buffer, 0, sizeof(buffer));
161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  memset(zero, 0, sizeof(zero));
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  HandleAttr attr;
163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Write the data to the file.
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(0, file.Write(attr, data, sizeof(data), &result_bytes));
166424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ASSERT_EQ(sizeof(data), result_bytes);
167424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
168424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Double the size of the file.
169424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, file.FTruncate(sizeof(data) * 2));
170424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, file.GetSize(&result_size));
171424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(sizeof(data) * 2, result_size);
172424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
173424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Read the first half of the file, it shouldn't have changed.
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(0, file.Read(attr, buffer, sizeof(buffer), &result_bytes));
175424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(sizeof(buffer), result_bytes);
176424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, memcmp(buffer, data, sizeof(buffer)));
177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
178424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Read the second half of the file, it should be all zeroes.
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  attr.offs = sizeof(data);
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(0, file.Read(attr, buffer, sizeof(buffer), &result_bytes));
181424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(sizeof(buffer), result_bytes);
182424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, memcmp(buffer, zero, sizeof(buffer)));
183424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
184424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Decrease the size of the file.
185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, file.FTruncate(100));
186424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, file.GetSize(&result_size));
187424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(100, result_size);
188424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Data should still be there.
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  attr.offs = 0;
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(0, file.Read(attr, buffer, sizeof(buffer), &result_bytes));
192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(100, result_bytes);
193424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, memcmp(buffer, data, 100));
194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
195424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MemFsNodeTest, Fcntl_GETFL) {
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MemFsNodeForTesting* node = new MemFsNodeForTesting();
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs(new MemFsForTesting());
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode file(node);
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  KernelHandle handle(fs, file);
2018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0, handle.Init(O_CREAT | O_APPEND));
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Test invalid fcntl command.
2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  ASSERT_EQ(ENOSYS, handle.Fcntl(-1, NULL));
2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Test F_GETFL
2078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0, node->Init(0));
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int flags = 0;
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(0, handle.Fcntl(F_GETFL, &flags));
2108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(O_CREAT | O_APPEND, flags);
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Test F_SETFL
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Test adding of O_NONBLOCK
2148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  flags = O_NONBLOCK | O_APPEND;
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(0, handle.Fcntl(F_SETFL, NULL, flags));
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(0, handle.Fcntl(F_GETFL, &flags));
2178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(O_CREAT | O_APPEND | O_NONBLOCK, flags);
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Clearing of O_APPEND should generate EPERM;
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  flags = O_NONBLOCK;
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ASSERT_EQ(EPERM, handle.Fcntl(F_SETFL, NULL, flags));
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MemFsNodeTest, Directory) {
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  s_alloc_num = 0;
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DirNodeForTesting root;
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode result_node;
228010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  off_t result_size = 0;
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result_bytes = 0;
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  root.Init(0);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test properties
2343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, root.GetLinks());
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Directories are always executable.
2368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  EXPECT_EQ(S_IRALL | S_IWALL | S_IXALL, root.GetMode());
2373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(S_IFDIR, root.GetType());
2383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(root.IsaDir());
2393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_FALSE(root.IsaFile());
240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  EXPECT_EQ(ENOTTY, root.Isatty());
2413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, root.RefCount());
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IO operations should fail
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf1[1024];
2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  HandleAttr attr;
2463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, root.GetSize(&result_size));
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(0, result_size);
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(EISDIR, root.Read(attr, buf1, sizeof(buf1), &result_bytes));
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(EISDIR, root.Write(attr, buf1, sizeof(buf1), &result_bytes));
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Chmod test
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(0, root.Fchmod(S_IRALL | S_IWALL));
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(S_IRALL | S_IWALL, root.GetMode());
2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Change it back.
2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_EQ(0, root.Fchmod(S_IRALL | S_IWALL | S_IXALL));
2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test directory operations
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MemFsNodeForTesting* raw_file = new MemFsNodeForTesting;
2598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  EXPECT_EQ(0, raw_file->Init(0));
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode file(raw_file);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, root.RefCount());
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, file->RefCount());
2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, root.AddChild("F1", file));
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, file->GetLinks());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, file->RefCount());
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that the directory is there
26968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const size_t kMaxDirents = 4;
27068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  struct dirent d[kMaxDirents];
27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_EQ(0, root.GetDents(0, &d[0], sizeof(d), &result_bytes));
27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
27368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  {
27468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    size_t num_dirents = result_bytes / sizeof(dirent);
27568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(3, num_dirents);
27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(sizeof(dirent) * num_dirents, result_bytes);
27768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
27868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    std::multiset<std::string> dirnames;
27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    for (int i = 0; i < num_dirents; ++i) {
28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EXPECT_LT(0, d[i].d_ino);  // 0 is an invalid inode number.
28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EXPECT_EQ(sizeof(dirent), d[i].d_off);
28268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      EXPECT_EQ(sizeof(dirent), d[i].d_reclen);
28368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      dirnames.insert(d[i].d_name);
28468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
28568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
28668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(1, dirnames.count("F1"));
28768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(1, dirnames.count("."));
28868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    EXPECT_EQ(1, dirnames.count(".."));
28968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
29068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // There should only be 3 entries. Reading past that will return 0 bytes read.
29268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_EQ(0, root.GetDents(sizeof(d), &d[0], sizeof(d), &result_bytes));
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(0, result_bytes);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, root.AddChild("F2", file));
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, file->GetLinks());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3, file->RefCount());
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(EEXIST, root.AddChild("F1", file));
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, file->GetLinks());
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(3, file->RefCount());
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2, s_alloc_num);
3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, root.FindChild("F1", &result_node));
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_NE(NULL_NODE, result_node.get());
3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, root.FindChild("F2", &result_node));
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_NE(NULL_NODE, result_node.get());
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(ENOENT, root.FindChild("F3", &result_node));
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(NULL_NODE, result_node.get());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2, s_alloc_num);
3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, root.RemoveChild("F1"));
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, file->GetLinks());
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, file->RefCount());
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ(0, root.RemoveChild("F2"));
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, file->GetLinks());
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, file->RefCount());
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(2, s_alloc_num);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  file.reset();
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(1, s_alloc_num);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(MemFsNodeTest, OpenMode) {
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MemFsNodeForTesting* node = new MemFsNodeForTesting();
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedFilesystem fs(new MemFsForTesting());
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ScopedNode file(node);
3278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const char write_buf[] = "hello world";
3298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  char read_buf[10];
3308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  int byte_count = 0;
3318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Write some data to the file
3338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  {
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    KernelHandle handle(fs, file);
3358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(0, handle.Init(O_CREAT | O_WRONLY));
3368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(0, handle.Write(write_buf, strlen(write_buf), &byte_count));
3378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(byte_count, strlen(write_buf));
3388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
3398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Reading from the O_WRONLY handle should be impossible
3418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  {
3428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    byte_count = 0;
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    KernelHandle handle(fs, file);
3448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(0, handle.Init(O_WRONLY));
3458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(EACCES, handle.Read(read_buf, 10, &byte_count));
3468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(0, handle.Write(write_buf, strlen(write_buf), &byte_count));
3478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(byte_count, strlen(write_buf));
3488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
3498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Writing to a O_RDONLY handle should fail
3518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  {
3528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    byte_count = 0;
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    KernelHandle handle(fs, file);
3548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(0, handle.Init(O_RDONLY));
3558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(EACCES, handle.Write(write_buf, strlen(write_buf), &byte_count));
3568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(0, handle.Read(read_buf, sizeof(read_buf), &byte_count));
3578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(byte_count, sizeof(read_buf));
3588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
3598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
360