Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / tests / nacl_io_test / filesystem_test.cc
1 // Copyright 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 "dev_fs_for_testing.h"
12 #include "gtest/gtest.h"
13 #include "nacl_io/filesystem.h"
14 #include "nacl_io/ioctl.h"
15 #include "nacl_io/kernel_handle.h"
16 #include "nacl_io/memfs/mem_fs.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 MemFsForTesting : public MemFs {
25  public:
26   MemFsForTesting() {
27     FsInitArgs args(1);
28     EXPECT_EQ(0, Init(args));
29   }
30
31   int num_nodes() { return (int)inode_pool_.size(); }
32 };
33
34 }  // namespace
35
36 TEST(FilesystemTest, Sanity) {
37   MemFsForTesting fs;
38
39   ScopedNode file;
40   ScopedNode root;
41   ScopedNode result_node;
42
43   off_t result_size = 0;
44   int result_bytes = 0;
45   char buf1[1024];
46
47   // A memory filesystem starts with one directory node: the root.
48   EXPECT_EQ(1, fs.num_nodes());
49
50   // Fail to open non existent file
51   EXPECT_EQ(ENOENT, fs.Access(Path("/foo"), R_OK | W_OK));
52   EXPECT_EQ(ENOENT, fs.Open(Path("/foo"), O_RDWR, &result_node));
53   EXPECT_EQ(NULL, result_node.get());
54   EXPECT_EQ(1, fs.num_nodes());
55
56   // Create a file
57   EXPECT_EQ(0, fs.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, fs.num_nodes());
63   EXPECT_EQ(2, file->RefCount());
64   EXPECT_EQ(0, fs.Access(Path("/foo"), R_OK | W_OK));
65   EXPECT_EQ(EACCES, fs.Access(Path("/foo"), X_OK));
66
67   // All access should be allowed on the root directory.
68   EXPECT_EQ(0, fs.Access(Path("/"), R_OK | W_OK | X_OK));
69   // Open the root directory for write should fail.
70   EXPECT_EQ(EISDIR, fs.Open(Path("/"), O_RDWR, &root));
71   EXPECT_EQ(2, fs.num_nodes());
72
73   // Open the root directory, should not create a new file
74   EXPECT_EQ(0, fs.Open(Path("/"), O_RDONLY, &root));
75   EXPECT_EQ(2, fs.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             fs.Open(Path("/foo"), O_RDWR | O_CREAT | O_EXCL, &result_node));
86   EXPECT_EQ(NULL_NODE, result_node.get());
87   EXPECT_EQ(2, fs.num_nodes());
88
89   // Fail to create a directory with the same name
90   EXPECT_EQ(EEXIST, fs.Mkdir(Path("/foo"), O_RDWR));
91   EXPECT_EQ(2, fs.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, fs.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, fs.Open(Path("/foo"), O_RDWR | O_CREAT, &result_node));
110   EXPECT_EQ(3, file->RefCount());
111   EXPECT_EQ(2, fs.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 Filesystem holds it
117   file.reset();
118   result_node.reset();
119   EXPECT_EQ(2, fs.num_nodes());
120
121   // This should have deleted the object
122   EXPECT_EQ(0, fs.Unlink(Path("/foo")));
123   EXPECT_EQ(1, fs.num_nodes());
124
125   // We should fail to find it
126   EXPECT_EQ(ENOENT, fs.Unlink(Path("/foo")));
127   EXPECT_EQ(1, fs.num_nodes());
128
129   // Recreate foo as a directory
130   EXPECT_EQ(0, fs.Mkdir(Path("/foo"), O_RDWR));
131   EXPECT_EQ(2, fs.num_nodes());
132
133   // Create a file (exclusively)
134   EXPECT_EQ(0, fs.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, fs.num_nodes());
138
139   // Attempt to delete the directory and fail
140   EXPECT_EQ(ENOTEMPTY, fs.Rmdir(Path("/foo")));
141   EXPECT_EQ(2, root->RefCount());
142   EXPECT_EQ(2, file->RefCount());
143   EXPECT_EQ(3, fs.num_nodes());
144
145   // Unlink the file, we should have the only file ref at this point.
146   EXPECT_EQ(0, fs.Unlink(Path("/foo/bar")));
147   EXPECT_EQ(2, root->RefCount());
148   EXPECT_EQ(1, file->RefCount());
149   EXPECT_EQ(3, fs.num_nodes());
150
151   // Deref the file, to make it go away
152   file.reset();
153   EXPECT_EQ(2, fs.num_nodes());
154
155   // Deref the directory
156   EXPECT_EQ(0, fs.Rmdir(Path("/foo")));
157   EXPECT_EQ(1, fs.num_nodes());
158
159   // Verify the directory is gone
160   EXPECT_EQ(ENOENT, fs.Access(Path("/foo"), F_OK));
161   EXPECT_EQ(ENOENT, fs.Open(Path("/foo"), O_RDWR, &file));
162   EXPECT_EQ(NULL_NODE, file.get());
163 }
164
165 TEST(FilesystemTest, OpenMode_TRUNC) {
166   MemFsForTesting fs;
167   ScopedNode file;
168   ScopedNode root;
169   ScopedNode result_node;
170   HandleAttr attrs;
171   int result_bytes;
172
173   // Open a file and write something to it.
174   const char* buf = "hello";
175   ASSERT_EQ(0, fs.Open(Path("/foo"), O_RDWR | O_CREAT, &file));
176   ASSERT_EQ(0, file->Write(attrs, buf, strlen(buf), &result_bytes));
177   ASSERT_EQ(strlen(buf), result_bytes);
178
179   // Open it again with TRUNC and make sure it is empty
180   char read_buf[10];
181   ASSERT_EQ(0, fs.Open(Path("/foo"), O_RDWR | O_TRUNC, &file));
182   ASSERT_EQ(0, file->Read(attrs, read_buf, sizeof(read_buf), &result_bytes));
183   ASSERT_EQ(0, result_bytes);
184 }
185
186 TEST(FilesystemTest, MemFsRemove) {
187   MemFsForTesting fs;
188   ScopedNode file;
189   ScopedNode result_node;
190
191   ASSERT_EQ(0, fs.Mkdir(Path("/dir"), O_RDWR));
192   ASSERT_EQ(0, fs.Open(Path("/file"), O_RDWR | O_CREAT | O_EXCL, &file));
193   EXPECT_NE(NULL_NODE, file.get());
194   EXPECT_EQ(3, fs.num_nodes());
195   file.reset();
196
197   EXPECT_EQ(0, fs.Remove(Path("/dir")));
198   EXPECT_EQ(2, fs.num_nodes());
199   EXPECT_EQ(0, fs.Remove(Path("/file")));
200   EXPECT_EQ(1, fs.num_nodes());
201
202   ASSERT_EQ(ENOENT, fs.Open(Path("/dir/foo"), O_CREAT | O_RDWR, &result_node));
203   ASSERT_EQ(NULL_NODE, result_node.get());
204   ASSERT_EQ(ENOENT, fs.Open(Path("/file"), O_RDONLY, &result_node));
205   ASSERT_EQ(NULL_NODE, result_node.get());
206 }
207
208 TEST(FilesystemTest, MemFsRename) {
209   MemFsForTesting fs;
210   ASSERT_EQ(0, fs.Mkdir(Path("/dir1"), O_RDWR));
211   ASSERT_EQ(0, fs.Mkdir(Path("/dir2"), O_RDWR));
212   ASSERT_EQ(3, fs.num_nodes());
213
214   ScopedNode file;
215   ASSERT_EQ(0, fs.Open(Path("/dir1/file"), O_RDWR | O_CREAT | O_EXCL, &file));
216   ASSERT_EQ(0, fs.Access(Path("/dir1/file"), R_OK));
217   ASSERT_EQ(4, fs.num_nodes());
218
219   // Move from one directory to another should ok
220   ASSERT_EQ(0, fs.Rename(Path("/dir1/file"), Path("/dir2/new_file")));
221   ASSERT_NE(0, fs.Access(Path("/dir1/file"), R_OK));
222   ASSERT_EQ(0, fs.Access(Path("/dir2/new_file"), R_OK));
223   ASSERT_EQ(4, fs.num_nodes());
224
225   // Move within the same directory
226   ASSERT_EQ(0, fs.Rename(Path("/dir2/new_file"), Path("/dir2/new_file2")));
227   ASSERT_NE(0, fs.Access(Path("/dir2/new_file"), R_OK));
228   ASSERT_EQ(0, fs.Access(Path("/dir2/new_file2"), R_OK));
229   ASSERT_EQ(4, fs.num_nodes());
230
231   // Move to another directory but without a filename
232   ASSERT_EQ(0, fs.Rename(Path("/dir2/new_file2"), Path("/dir1")));
233   ASSERT_NE(0, fs.Access(Path("/dir2/new_file2"), R_OK));
234   ASSERT_EQ(0, fs.Access(Path("/dir1/new_file2"), R_OK));
235   ASSERT_EQ(4, fs.num_nodes());
236 }
237
238 TEST(FilesystemTest, MemFsRenameDir) {
239   MemFsForTesting fs;
240
241   ASSERT_EQ(0, fs.Mkdir(Path("/dir1"), O_RDWR));
242   ASSERT_EQ(0, fs.Mkdir(Path("/dir2"), O_RDWR));
243   EXPECT_EQ(3, fs.num_nodes());
244
245   // Renaming one directory to another should work
246   ASSERT_EQ(0, fs.Rename(Path("/dir1"), Path("/dir2")));
247   ASSERT_NE(0, fs.Access(Path("/dir1"), R_OK));
248   ASSERT_EQ(0, fs.Access(Path("/dir2"), R_OK));
249   EXPECT_EQ(2, fs.num_nodes());
250
251   // Reset to initial state
252   ASSERT_EQ(0, fs.Mkdir(Path("/dir1"), O_RDWR));
253   EXPECT_EQ(3, fs.num_nodes());
254
255   // Renaming a directory to a new name within another
256   ASSERT_EQ(0, fs.Rename(Path("/dir1"), Path("/dir2/foo")));
257   ASSERT_EQ(0, fs.Access(Path("/dir2"), R_OK));
258   ASSERT_EQ(0, fs.Access(Path("/dir2/foo"), R_OK));
259   EXPECT_EQ(3, fs.num_nodes());
260
261   // Reset to initial state
262   ASSERT_EQ(0, fs.Rmdir(Path("/dir2/foo")));
263   ASSERT_EQ(0, fs.Mkdir(Path("/dir1"), O_RDWR));
264   EXPECT_EQ(3, fs.num_nodes());
265
266   // Renaming one directory to another should fail if the target is non-empty
267   ASSERT_EQ(0, fs.Mkdir(Path("/dir2/dir3"), O_RDWR));
268   ASSERT_EQ(ENOTEMPTY, fs.Rename(Path("/dir1"), Path("/dir2")));
269 }
270
271 TEST(FilesystemTest, DevAccess) {
272   // Should not be able to open non-existent file.
273   FakePepperInterface pepper;
274   DevFsForTesting fs(&pepper);
275   ScopedNode invalid_node, valid_node;
276   ASSERT_EQ(ENOENT, fs.Access(Path("/foo"), F_OK));
277   // Creating non-existent file should return EACCES
278   ASSERT_EQ(EACCES, fs.Open(Path("/foo"), O_CREAT | O_RDWR, &invalid_node));
279
280   // We should be able to open all existing nodes with O_CREAT and O_RDWR.
281   ASSERT_EQ(0, fs.Open(Path("/null"), O_CREAT | O_RDWR, &valid_node));
282   ASSERT_EQ(0, fs.Open(Path("/zero"), O_CREAT | O_RDWR, &valid_node));
283   ASSERT_EQ(0, fs.Open(Path("/urandom"), O_CREAT | O_RDWR, &valid_node));
284   ASSERT_EQ(0, fs.Open(Path("/console0"), O_CREAT | O_RDWR, &valid_node));
285   ASSERT_EQ(0, fs.Open(Path("/console1"), O_CREAT | O_RDWR, &valid_node));
286   ASSERT_EQ(0, fs.Open(Path("/console3"), O_CREAT | O_RDWR, &valid_node));
287   ASSERT_EQ(0, fs.Open(Path("/tty"), O_CREAT | O_RDWR, &valid_node));
288   ASSERT_EQ(0, fs.Open(Path("/stdin"), O_CREAT | O_RDWR, &valid_node));
289   ASSERT_EQ(0, fs.Open(Path("/stdout"), O_CREAT | O_RDWR, &valid_node));
290   ASSERT_EQ(0, fs.Open(Path("/stderr"), O_CREAT | O_RDWR, &valid_node));
291 }
292
293 TEST(FilesystemTest, DevNull) {
294   FakePepperInterface pepper;
295   DevFsForTesting fs(&pepper);
296   ScopedNode dev_null;
297   int result_bytes = 0;
298
299   ASSERT_EQ(0, fs.Access(Path("/null"), R_OK | W_OK));
300   ASSERT_EQ(EACCES, fs.Access(Path("/null"), X_OK));
301   ASSERT_EQ(0, fs.Open(Path("/null"), O_RDWR, &dev_null));
302   ASSERT_NE(NULL_NODE, dev_null.get());
303
304   // Writing to /dev/null should write everything.
305   const char msg[] = "Dummy test message.";
306   HandleAttr attrs;
307   EXPECT_EQ(0, dev_null->Write(attrs, &msg[0], strlen(msg), &result_bytes));
308   EXPECT_EQ(strlen(msg), result_bytes);
309
310   // Reading from /dev/null should read nothing.
311   const int kBufferLength = 100;
312   char buffer[kBufferLength];
313   EXPECT_EQ(0, dev_null->Read(attrs, &buffer[0], kBufferLength, &result_bytes));
314   EXPECT_EQ(0, result_bytes);
315 }
316
317 TEST(FilesystemTest, DevZero) {
318   FakePepperInterface pepper;
319   DevFsForTesting fs(&pepper);
320   ScopedNode dev_zero;
321   int result_bytes = 0;
322
323   ASSERT_EQ(0, fs.Access(Path("/zero"), R_OK | W_OK));
324   ASSERT_EQ(EACCES, fs.Access(Path("/zero"), X_OK));
325   ASSERT_EQ(0, fs.Open(Path("/zero"), O_RDWR, &dev_zero));
326   ASSERT_NE(NULL_NODE, dev_zero.get());
327
328   // Writing to /dev/zero should write everything.
329   HandleAttr attrs;
330   const char msg[] = "Dummy test message.";
331   EXPECT_EQ(0, dev_zero->Write(attrs, &msg[0], strlen(msg), &result_bytes));
332   EXPECT_EQ(strlen(msg), result_bytes);
333
334   // Reading from /dev/zero should read all zeroes.
335   const int kBufferLength = 100;
336   char buffer[kBufferLength];
337   // First fill with all 1s.
338   memset(&buffer[0], 0x1, kBufferLength);
339   EXPECT_EQ(0, dev_zero->Read(attrs, &buffer[0], kBufferLength, &result_bytes));
340   EXPECT_EQ(kBufferLength, result_bytes);
341
342   char zero_buffer[kBufferLength];
343   memset(&zero_buffer[0], 0, kBufferLength);
344   EXPECT_EQ(0, memcmp(&buffer[0], &zero_buffer[0], kBufferLength));
345 }
346
347 // Disabled due to intermittent failures on linux: http://crbug.com/257257
348 TEST(FilesystemTest, DISABLED_DevUrandom) {
349   FakePepperInterface pepper;
350   DevFsForTesting fs(&pepper);
351   ScopedNode dev_urandom;
352   int result_bytes = 0;
353
354   ASSERT_EQ(0, fs.Access(Path("/urandom"), R_OK | W_OK));
355   ASSERT_EQ(EACCES, fs.Access(Path("/urandom"), X_OK));
356   ASSERT_EQ(0, fs.Open(Path("/urandom"), O_RDWR, &dev_urandom));
357   ASSERT_NE(NULL_NODE, dev_urandom.get());
358
359   // Writing to /dev/urandom should write everything.
360   const char msg[] = "Dummy test message.";
361   HandleAttr attrs;
362   EXPECT_EQ(0, dev_urandom->Write(attrs, &msg[0], strlen(msg), &result_bytes));
363   EXPECT_EQ(strlen(msg), result_bytes);
364
365   // Reading from /dev/urandom should read random bytes.
366   const int kSampleBatches = 1000;
367   const int kSampleBatchSize = 1000;
368   const int kTotalSamples = kSampleBatches * kSampleBatchSize;
369
370   int byte_count[256] = {0};
371
372   unsigned char buffer[kSampleBatchSize];
373   for (int batch = 0; batch < kSampleBatches; ++batch) {
374     int bytes_read = 0;
375     EXPECT_EQ(
376         0, dev_urandom->Read(attrs, &buffer[0], kSampleBatchSize, &bytes_read));
377     EXPECT_EQ(kSampleBatchSize, bytes_read);
378
379     for (int i = 0; i < bytes_read; ++i) {
380       byte_count[buffer[i]]++;
381     }
382   }
383
384   double expected_count = kTotalSamples / 256.;
385   double chi_squared = 0;
386   for (int i = 0; i < 256; ++i) {
387     double difference = byte_count[i] - expected_count;
388     chi_squared += difference * difference / expected_count;
389   }
390
391   // Approximate chi-squared value for p-value 0.05, 255 degrees-of-freedom.
392   EXPECT_LE(chi_squared, 293.24);
393 }