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.
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"
20 using namespace nacl_io;
24 class MountMemMock : public MountMem {
28 EXPECT_EQ(0, Init(1, map, NULL));
31 int num_nodes() { return (int) inode_pool_.size(); }
36 TEST(MountTest, Sanity) {
41 ScopedMountNode result_node;
43 size_t result_size = 0;
47 // A memory mount starts with one directory node: the root.
48 EXPECT_EQ(1, mnt.num_nodes());
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());
57 EXPECT_EQ(0, mnt.Open(Path("/foo"), O_RDWR | O_CREAT, &file));
58 ASSERT_NE(NULL_NODE, file.get());
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));
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());
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];
79 EXPECT_EQ(0, root->GetDents(0, dirs, sizeof(dirs), &len));
80 // 3 == "foo", ".", ".."
81 EXPECT_EQ(3 * sizeof(struct dirent), len);
83 // Fail to re-create the same file
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());
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());
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());
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);
116 // Remove our references so that only the Mount holds it
119 EXPECT_EQ(2, mnt.num_nodes());
121 // This should have deleted the object
122 EXPECT_EQ(0, mnt.Unlink(Path("/foo")));
123 EXPECT_EQ(1, mnt.num_nodes());
125 // We should fail to find it
126 EXPECT_EQ(ENOENT, mnt.Unlink(Path("/foo")));
127 EXPECT_EQ(1, mnt.num_nodes());
129 // Recreate foo as a directory
130 EXPECT_EQ(0, mnt.Mkdir(Path("/foo"), O_RDWR));
131 EXPECT_EQ(2, mnt.num_nodes());
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());
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());
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());
152 // Deref the file, to make it go away
154 EXPECT_EQ(2, mnt.num_nodes());
156 // Deref the directory
157 EXPECT_EQ(0, mnt.Rmdir(Path("/foo")));
158 EXPECT_EQ(1, mnt.num_nodes());
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());
166 TEST(MountTest, MemMountRemove) {
168 ScopedMountNode file;
169 ScopedMountNode result_node;
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());
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());
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());
189 TEST(MountTest, DevAccess) {
190 // Should not be able to open non-existent file.
192 ASSERT_EQ(ENOENT, mnt.Access(Path("/foo"), F_OK));
195 TEST(MountTest, DevNull) {
197 ScopedMountNode dev_null;
198 int result_bytes = 0;
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());
205 // Writing to /dev/null should write everything.
206 const char msg[] = "Dummy test message.";
208 EXPECT_EQ(0, dev_null->Write(attrs, &msg[0], strlen(msg), &result_bytes));
209 EXPECT_EQ(strlen(msg), result_bytes);
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);
218 TEST(MountTest, DevZero) {
220 ScopedMountNode dev_zero;
221 int result_bytes = 0;
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());
228 // Writing to /dev/zero should write everything.
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);
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);
242 char zero_buffer[kBufferLength];
243 memset(&zero_buffer[0], 0, kBufferLength);
244 EXPECT_EQ(0, memcmp(&buffer[0], &zero_buffer[0], kBufferLength));
247 // Disabled due to intermittent failures on linux: http://crbug.com/257257
248 TEST(MountTest, DISABLED_DevUrandom) {
250 ScopedMountNode dev_urandom;
251 int result_bytes = 0;
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());
258 // Writing to /dev/urandom should write everything.
259 const char msg[] = "Dummy test message.";
261 EXPECT_EQ(0, dev_urandom->Write(attrs, &msg[0], strlen(msg), &result_bytes));
262 EXPECT_EQ(strlen(msg), result_bytes);
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;
269 int byte_count[256] = {0};
271 unsigned char buffer[kSampleBatchSize];
272 for (int batch = 0; batch < kSampleBatches; ++batch) {
274 EXPECT_EQ(0, dev_urandom->Read(attrs, &buffer[0], kSampleBatchSize,
276 EXPECT_EQ(kSampleBatchSize, bytes_read);
278 for (int i = 0; i < bytes_read; ++i) {
279 byte_count[buffer[i]]++;
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;
290 // Approximate chi-squared value for p-value 0.05, 255 degrees-of-freedom.
291 EXPECT_LE(chi_squared, 293.24);