Home | History | Annotate | Download | only in nacl_io_test
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <errno.h>
      6 #include <fcntl.h>
      7 
      8 #include "nacl_io/error.h"
      9 #include "nacl_io/ioctl.h"
     10 #include "nacl_io/kernel_proxy.h"
     11 #include "nacl_io/mount_dev.h"
     12 #include "nacl_io/mount_node.h"
     13 #include "nacl_io/mount_node_dir.h"
     14 #include "nacl_io/mount_node_mem.h"
     15 #include "nacl_io/osdirent.h"
     16 
     17 #include "gtest/gtest.h"
     18 
     19 #define NULL_NODE ((MountNode*) NULL)
     20 
     21 using namespace nacl_io;
     22 
     23 static int s_AllocNum = 0;
     24 
     25 class MockMemory : public MountNodeMem {
     26  public:
     27   MockMemory() : MountNodeMem(NULL) { s_AllocNum++; }
     28 
     29   ~MockMemory() { s_AllocNum--; }
     30 
     31   Error Init(int mode) { return MountNodeMem::Init(mode); }
     32   Error AddChild(const std::string& name, const ScopedMountNode& node) {
     33     return MountNodeMem::AddChild(name, node);
     34   }
     35   Error RemoveChild(const std::string& name) {
     36     return MountNodeMem::RemoveChild(name);
     37   }
     38   Error FindChild(const std::string& name, ScopedMountNode* out_node) {
     39     return MountNodeMem::FindChild(name, out_node);
     40   }
     41   void Link() { MountNodeMem::Link(); }
     42   void Unlink() { MountNodeMem::Unlink(); }
     43 
     44  protected:
     45   using MountNodeMem::Init;
     46 };
     47 
     48 class MockDir : public MountNodeDir {
     49  public:
     50   MockDir() : MountNodeDir(NULL) { s_AllocNum++; }
     51 
     52   ~MockDir() { s_AllocNum--; }
     53 
     54   Error Init(int mode) { return MountNodeDir::Init(mode); }
     55   Error AddChild(const std::string& name, const ScopedMountNode& node) {
     56     return MountNodeDir::AddChild(name, node);
     57   }
     58   Error RemoveChild(const std::string& name) {
     59     return MountNodeDir::RemoveChild(name);
     60   }
     61   Error FindChild(const std::string& name, ScopedMountNode* out_node) {
     62     return MountNodeDir::FindChild(name, out_node);
     63   }
     64   void Link() { MountNodeDir::Link(); }
     65   void Unlink() { MountNodeDir::Unlink(); }
     66 
     67  protected:
     68   using MountNodeDir::Init;
     69 };
     70 
     71 TEST(MountNodeTest, File) {
     72   MockMemory* file = new MockMemory;
     73   ScopedMountNode result_node;
     74   size_t result_size = 0;
     75   int result_bytes = 0;
     76 
     77   EXPECT_EQ(0, file->Init(S_IREAD | S_IWRITE));
     78 
     79   // Test properties
     80   EXPECT_EQ(0, file->GetLinks());
     81   EXPECT_EQ(S_IREAD | S_IWRITE, file->GetMode());
     82   EXPECT_EQ(S_IFREG, file->GetType());
     83   EXPECT_FALSE(file->IsaDir());
     84   EXPECT_TRUE(file->IsaFile());
     85   EXPECT_FALSE(file->IsaTTY());
     86   EXPECT_EQ(0, file->RefCount());
     87 
     88   // Test IO
     89   char buf1[1024];
     90   char buf2[1024 * 2];
     91   for (size_t a = 0; a < sizeof(buf1); a++)
     92     buf1[a] = a;
     93   memset(buf2, 0, sizeof(buf2));
     94 
     95   EXPECT_EQ(0, file->GetSize(&result_size));
     96   EXPECT_EQ(0, result_size);
     97   EXPECT_EQ(0, file->Read(0, buf2, sizeof(buf2), &result_bytes));
     98   EXPECT_EQ(0, result_bytes);
     99   EXPECT_EQ(0, file->GetSize(&result_size));
    100   EXPECT_EQ(0, result_size);
    101   EXPECT_EQ(0, file->Write(0, buf1, sizeof(buf1), &result_bytes));
    102   EXPECT_EQ(sizeof(buf1), result_bytes);
    103   EXPECT_EQ(0, file->GetSize(&result_size));
    104   EXPECT_EQ(sizeof(buf1), result_size);
    105   EXPECT_EQ(0, file->Read(0, buf2, sizeof(buf2), &result_bytes));
    106   EXPECT_EQ(sizeof(buf1), result_bytes);
    107   EXPECT_EQ(0, memcmp(buf1, buf2, sizeof(buf1)));
    108 
    109   struct stat s;
    110   EXPECT_EQ(0, file->GetStat(&s));
    111   EXPECT_LT(0, s.st_ino);  // 0 is an invalid inode number.
    112   EXPECT_EQ(sizeof(buf1), s.st_size);
    113 
    114   // Directory operations should fail
    115   struct dirent d;
    116   EXPECT_EQ(ENOTDIR, file->GetDents(0, &d, sizeof(d), &result_bytes));
    117   EXPECT_EQ(ENOTDIR, file->AddChild("", result_node));
    118   EXPECT_EQ(ENOTDIR, file->RemoveChild(""));
    119   EXPECT_EQ(ENOTDIR, file->FindChild("", &result_node));
    120   EXPECT_EQ(NULL_NODE, result_node.get());
    121 
    122   delete file;
    123 }
    124 
    125 TEST(MountNodeTest, Directory) {
    126   MockDir* root = new MockDir();
    127   ScopedMountNode result_node;
    128   size_t result_size = 0;
    129   int result_bytes = 0;
    130 
    131   root->Init(S_IREAD | S_IWRITE);
    132 
    133   // Test properties
    134   EXPECT_EQ(0, root->GetLinks());
    135   EXPECT_EQ(S_IREAD | S_IWRITE, root->GetMode());
    136   EXPECT_EQ(S_IFDIR, root->GetType());
    137   EXPECT_TRUE(root->IsaDir());
    138   EXPECT_FALSE(root->IsaFile());
    139   EXPECT_FALSE(root->IsaTTY());
    140   EXPECT_EQ(0, root->RefCount());
    141 
    142   // IO operations should fail
    143   char buf1[1024];
    144   EXPECT_EQ(0, root->GetSize(&result_size));
    145   EXPECT_EQ(0, result_size);
    146   EXPECT_EQ(EISDIR, root->Read(0, buf1, sizeof(buf1), &result_bytes));
    147   EXPECT_EQ(EISDIR, root->Write(0, buf1, sizeof(buf1), &result_bytes));
    148 
    149   // Test directory operations
    150   MockMemory* raw_file = new MockMemory;
    151   EXPECT_EQ(0, raw_file->Init(S_IREAD | S_IWRITE));
    152   ScopedMountNode file(raw_file);
    153 
    154   EXPECT_EQ(0, root->RefCount());
    155   EXPECT_EQ(1, file->RefCount());
    156   EXPECT_EQ(0, root->AddChild("F1", file));
    157   EXPECT_EQ(1, file->GetLinks());
    158   EXPECT_EQ(2, file->RefCount());
    159 
    160   // Test that the directory is there
    161   struct dirent d;
    162   EXPECT_EQ(0, root->GetDents(0, &d, sizeof(d), &result_bytes));
    163   EXPECT_EQ(sizeof(d), result_bytes);
    164   EXPECT_LT(0, d.d_ino);  // 0 is an invalid inode number.
    165   EXPECT_EQ(sizeof(d), d.d_off);
    166   EXPECT_EQ(sizeof(d), d.d_reclen);
    167   EXPECT_EQ(0, strcmp("F1", d.d_name));
    168   EXPECT_EQ(0, root->GetDents(sizeof(d), &d, sizeof(d), &result_bytes));
    169   EXPECT_EQ(0, result_bytes);
    170 
    171   EXPECT_EQ(0, root->AddChild("F2", file));
    172   EXPECT_EQ(2, file->GetLinks());
    173   EXPECT_EQ(3, file->RefCount());
    174   EXPECT_EQ(EEXIST, root->AddChild("F1", file));
    175   EXPECT_EQ(2, file->GetLinks());
    176   EXPECT_EQ(3, file->RefCount());
    177 
    178   EXPECT_EQ(2, s_AllocNum);
    179   EXPECT_EQ(0, root->FindChild("F1", &result_node));
    180   EXPECT_NE(NULL_NODE, result_node.get());
    181   EXPECT_EQ(0, root->FindChild("F2", &result_node));
    182   EXPECT_NE(NULL_NODE, result_node.get());
    183   EXPECT_EQ(ENOENT, root->FindChild("F3", &result_node));
    184   EXPECT_EQ(NULL_NODE, result_node.get());
    185 
    186   EXPECT_EQ(2, s_AllocNum);
    187   EXPECT_EQ(0, root->RemoveChild("F1"));
    188   EXPECT_EQ(1, file->GetLinks());
    189   EXPECT_EQ(2, file->RefCount());
    190   EXPECT_EQ(0, root->RemoveChild("F2"));
    191   EXPECT_EQ(0, file->GetLinks());
    192   EXPECT_EQ(1, file->RefCount());
    193   EXPECT_EQ(2, s_AllocNum);
    194 
    195   file.reset();
    196   EXPECT_EQ(1, s_AllocNum);
    197 }
    198