- add sources.
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / tests / nacl_io_test / mount_test.cc
1 // Copyright (c) 2013 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 #include <string.h>
8 #include <sys/stat.h>
9 #include <string>
10
11 #include "gtest/gtest.h"
12 #include "mount_dev_mock.h"
13 #include "nacl_io/ioctl.h"
14 #include "nacl_io/kernel_handle.h"
15 #include "nacl_io/mount.h"
16 #include "nacl_io/mount_mem.h"
17 #include "nacl_io/osdirent.h"
18 #include "nacl_io/osunistd.h"
19
20 using namespace nacl_io;
21
22 namespace {
23
24 class MountMemMock : public MountMem {
25  public:
26   MountMemMock() {
27     StringMap_t map;
28     EXPECT_EQ(0, Init(1, map, NULL));
29   }
30
31   int num_nodes() { return (int) inode_pool_.size(); }
32 };
33
34 }  // namespace
35
36 TEST(MountTest, Sanity) {
37   MountMemMock mnt;
38
39   ScopedMountNode file;
40   ScopedMountNode root;
41   ScopedMountNode result_node;
42
43   size_t result_size = 0;
44   int result_bytes = 0;
45   char buf1[1024];
46
47   // A memory mount starts with one directory node: the root.
48   EXPECT_EQ(1, mnt.num_nodes());
49
50   // Fail to open non existent file
51   EXPECT_EQ(ENOENT, mnt.Access(Path("/foo"), R_OK | W_OK));
52   EXPECT_EQ(ENOENT, mnt.Open(Path("/foo"), O_RDWR, &result_node));
53   EXPECT_EQ(NULL, result_node.get());
54   EXPECT_EQ(1, mnt.num_nodes());
55
56   // Create a file
57   EXPECT_EQ(0, mnt.Open(Path("/foo"), O_RDWR | O_CREAT, &file));
58   ASSERT_NE(NULL_NODE, file.get());
59
60   // We now have a directory and a file.  The file has a two references
61   // one returned to the test, one for the name->inode map.
62   EXPECT_EQ(2, mnt.num_nodes());
63   EXPECT_EQ(2, file->RefCount());
64   EXPECT_EQ(0, mnt.Access(Path("/foo"), R_OK | W_OK));
65   EXPECT_EQ(EACCES, mnt.Access(Path("/foo"), X_OK));
66
67   // All access should be allowed on the root directory.
68   EXPECT_EQ(0, mnt.Access(Path("/"), R_OK | W_OK | X_OK));
69   // Open the root directory for write should fail.
70   EXPECT_EQ(EISDIR, mnt.Open(Path("/"), O_RDWR, &root));
71   EXPECT_EQ(2, mnt.num_nodes());
72
73   // Open the root directory, should not create a new file
74   EXPECT_EQ(0, mnt.Open(Path("/"), O_RDONLY, &root));
75   EXPECT_EQ(2, mnt.num_nodes());
76   ASSERT_NE(NULL_NODE, root.get());
77   struct dirent dirs[4];
78   int len;
79   EXPECT_EQ(0, root->GetDents(0, dirs, sizeof(dirs), &len));
80   // 3 == "foo", ".", ".."
81   EXPECT_EQ(3 * sizeof(struct dirent), len);
82
83   // Fail to re-create the same file
84   EXPECT_EQ(EEXIST,
85             mnt.Open(Path("/foo"), O_RDWR | O_CREAT | O_EXCL, &result_node));
86   EXPECT_EQ(NULL_NODE, result_node.get());
87   EXPECT_EQ(2, mnt.num_nodes());
88
89   // Fail to create a directory with the same name
90   EXPECT_EQ(EEXIST, mnt.Mkdir(Path("/foo"), O_RDWR));
91   EXPECT_EQ(2, mnt.num_nodes());
92
93   HandleAttr attrs;
94
95   // Attempt to READ/WRITE
96   EXPECT_EQ(0, file->GetSize(&result_size));
97   EXPECT_EQ(0, result_size);
98   EXPECT_EQ(0, file->Write(attrs, buf1, sizeof(buf1), &result_bytes));
99   EXPECT_EQ(sizeof(buf1), result_bytes);
100   EXPECT_EQ(0, file->GetSize(&result_size));
101   EXPECT_EQ(sizeof(buf1), result_size);
102   EXPECT_EQ(0, file->Read(attrs, buf1, sizeof(buf1), &result_bytes));
103   EXPECT_EQ(sizeof(buf1), result_bytes);
104   EXPECT_EQ(2, mnt.num_nodes());
105   EXPECT_EQ(2, file->RefCount());
106
107   // Attempt to open the same file, create another ref to it, but does not
108   // create a new file.
109   EXPECT_EQ(0, mnt.Open(Path("/foo"), O_RDWR | O_CREAT, &result_node));
110   EXPECT_EQ(3, file->RefCount());
111   EXPECT_EQ(2, mnt.num_nodes());
112   EXPECT_EQ(file.get(), result_node.get());
113   EXPECT_EQ(0, file->GetSize(&result_size));
114   EXPECT_EQ(sizeof(buf1), result_size);
115
116   // Remove our references so that only the Mount holds it
117   file.reset();
118   result_node.reset();
119   EXPECT_EQ(2, mnt.num_nodes());
120
121   // This should have deleted the object
122   EXPECT_EQ(0, mnt.Unlink(Path("/foo")));
123   EXPECT_EQ(1, mnt.num_nodes());
124
125   // We should fail to find it
126   EXPECT_EQ(ENOENT, mnt.Unlink(Path("/foo")));
127   EXPECT_EQ(1, mnt.num_nodes());
128
129   // Recreate foo as a directory
130   EXPECT_EQ(0, mnt.Mkdir(Path("/foo"), O_RDWR));
131   EXPECT_EQ(2, mnt.num_nodes());
132
133   // Create a file (exclusively)
134   EXPECT_EQ(0, mnt.Open(Path("/foo/bar"), O_RDWR | O_CREAT | O_EXCL, &file));
135   ASSERT_NE(NULL_NODE, file.get());
136   EXPECT_EQ(2, file->RefCount());
137   EXPECT_EQ(3, mnt.num_nodes());
138
139   // Attempt to delete the directory and fail
140   EXPECT_EQ(ENOTEMPTY, mnt.Rmdir(Path("/foo")));
141   EXPECT_EQ(2, root->RefCount());
142   EXPECT_EQ(2, file->RefCount());
143   EXPECT_EQ(3, mnt.num_nodes());
144
145   // Unlink the file, we should have the only file ref at this point.
146   EXPECT_EQ(0, mnt.Unlink(Path("/foo/bar")));
147   EXPECT_EQ(2, root->RefCount());
148   EXPECT_EQ(1, file->RefCount());
149   EXPECT_EQ(3, mnt.num_nodes());
150
151
152   // Deref the file, to make it go away
153   file.reset();
154   EXPECT_EQ(2, mnt.num_nodes());
155
156   // Deref the directory
157   EXPECT_EQ(0, mnt.Rmdir(Path("/foo")));
158   EXPECT_EQ(1, mnt.num_nodes());
159
160   // Verify the directory is gone
161   EXPECT_EQ(ENOENT, mnt.Access(Path("/foo"), F_OK));
162   EXPECT_EQ(ENOENT, mnt.Open(Path("/foo"), O_RDWR, &file));
163   EXPECT_EQ(NULL_NODE, file.get());
164 }
165
166 TEST(MountTest, MemMountRemove) {
167   MountMemMock mnt;
168   ScopedMountNode file;
169   ScopedMountNode result_node;
170
171   EXPECT_EQ(0, mnt.Mkdir(Path("/dir"), O_RDWR));
172   EXPECT_EQ(0, mnt.Open(Path("/file"), O_RDWR | O_CREAT | O_EXCL, &file));
173   EXPECT_NE(NULL_NODE, file.get());
174   EXPECT_EQ(3, mnt.num_nodes());
175   file.reset();
176
177   EXPECT_EQ(0, mnt.Remove(Path("/dir")));
178   EXPECT_EQ(2, mnt.num_nodes());
179   EXPECT_EQ(0, mnt.Remove(Path("/file")));
180   EXPECT_EQ(1, mnt.num_nodes());
181
182   EXPECT_EQ(ENOENT,
183             mnt.Open(Path("/dir/foo"), O_CREAT | O_RDWR, &result_node));
184   EXPECT_EQ(NULL_NODE, result_node.get());
185   EXPECT_EQ(ENOENT, mnt.Open(Path("/file"), O_RDONLY, &result_node));
186   EXPECT_EQ(NULL_NODE, result_node.get());
187 }
188
189 TEST(MountTest, DevAccess) {
190   // Should not be able to open non-existent file.
191   MountDevMock mnt;
192   ASSERT_EQ(ENOENT, mnt.Access(Path("/foo"), F_OK));
193 }
194
195 TEST(MountTest, DevNull) {
196   MountDevMock mnt;
197   ScopedMountNode dev_null;
198   int result_bytes = 0;
199
200   ASSERT_EQ(0, mnt.Access(Path("/null"), R_OK | W_OK));
201   ASSERT_EQ(EACCES, mnt.Access(Path("/null"), X_OK));
202   ASSERT_EQ(0, mnt.Open(Path("/null"), O_RDWR, &dev_null));
203   ASSERT_NE(NULL_NODE, dev_null.get());
204
205   // Writing to /dev/null should write everything.
206   const char msg[] = "Dummy test message.";
207   HandleAttr attrs;
208   EXPECT_EQ(0, dev_null->Write(attrs, &msg[0], strlen(msg), &result_bytes));
209   EXPECT_EQ(strlen(msg), result_bytes);
210
211   // Reading from /dev/null should read nothing.
212   const int kBufferLength = 100;
213   char buffer[kBufferLength];
214   EXPECT_EQ(0, dev_null->Read(attrs, &buffer[0], kBufferLength, &result_bytes));
215   EXPECT_EQ(0, result_bytes);
216 }
217
218 TEST(MountTest, DevZero) {
219   MountDevMock mnt;
220   ScopedMountNode dev_zero;
221   int result_bytes = 0;
222
223   ASSERT_EQ(0, mnt.Access(Path("/zero"), R_OK | W_OK));
224   ASSERT_EQ(EACCES, mnt.Access(Path("/zero"), X_OK));
225   ASSERT_EQ(0, mnt.Open(Path("/zero"), O_RDWR, &dev_zero));
226   ASSERT_NE(NULL_NODE, dev_zero.get());
227
228   // Writing to /dev/zero should write everything.
229   HandleAttr attrs;
230   const char msg[] = "Dummy test message.";
231   EXPECT_EQ(0, dev_zero->Write(attrs, &msg[0], strlen(msg), &result_bytes));
232   EXPECT_EQ(strlen(msg), result_bytes);
233
234   // Reading from /dev/zero should read all zeroes.
235   const int kBufferLength = 100;
236   char buffer[kBufferLength];
237   // First fill with all 1s.
238   memset(&buffer[0], 0x1, kBufferLength);
239   EXPECT_EQ(0, dev_zero->Read(attrs, &buffer[0], kBufferLength, &result_bytes));
240   EXPECT_EQ(kBufferLength, result_bytes);
241
242   char zero_buffer[kBufferLength];
243   memset(&zero_buffer[0], 0, kBufferLength);
244   EXPECT_EQ(0, memcmp(&buffer[0], &zero_buffer[0], kBufferLength));
245 }
246
247 // Disabled due to intermittent failures on linux: http://crbug.com/257257
248 TEST(MountTest, DISABLED_DevUrandom) {
249   MountDevMock mnt;
250   ScopedMountNode dev_urandom;
251   int result_bytes = 0;
252
253   ASSERT_EQ(0, mnt.Access(Path("/urandom"), R_OK | W_OK));
254   ASSERT_EQ(EACCES, mnt.Access(Path("/urandom"), X_OK));
255   ASSERT_EQ(0, mnt.Open(Path("/urandom"), O_RDWR, &dev_urandom));
256   ASSERT_NE(NULL_NODE, dev_urandom.get());
257
258   // Writing to /dev/urandom should write everything.
259   const char msg[] = "Dummy test message.";
260   HandleAttr attrs;
261   EXPECT_EQ(0, dev_urandom->Write(attrs, &msg[0], strlen(msg), &result_bytes));
262   EXPECT_EQ(strlen(msg), result_bytes);
263
264   // Reading from /dev/urandom should read random bytes.
265   const int kSampleBatches = 1000;
266   const int kSampleBatchSize = 1000;
267   const int kTotalSamples = kSampleBatches * kSampleBatchSize;
268
269   int byte_count[256] = {0};
270
271   unsigned char buffer[kSampleBatchSize];
272   for (int batch = 0; batch < kSampleBatches; ++batch) {
273     int bytes_read = 0;
274     EXPECT_EQ(0, dev_urandom->Read(attrs, &buffer[0], kSampleBatchSize,
275                                    &bytes_read));
276     EXPECT_EQ(kSampleBatchSize, bytes_read);
277
278     for (int i = 0; i < bytes_read; ++i) {
279       byte_count[buffer[i]]++;
280     }
281   }
282
283   double expected_count = kTotalSamples / 256.;
284   double chi_squared = 0;
285   for (int i = 0; i < 256; ++i) {
286     double difference = byte_count[i] - expected_count;
287     chi_squared += difference * difference / expected_count;
288   }
289
290   // Approximate chi-squared value for p-value 0.05, 255 degrees-of-freedom.
291   EXPECT_LE(chi_squared, 293.24);
292 }