Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / native_client_sdk / src / tests / nacl_io_test / kernel_proxy_test.cc
blob9069e0fbd68f0d9899f43dbb99ce809f12b6678e
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.
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <pthread.h>
8 #include <stdio.h>
9 #include <sys/stat.h>
10 #include <sys/types.h>
11 #include <utime.h>
13 #include <map>
14 #include <string>
16 #include "gmock/gmock.h"
17 #include "gtest/gtest.h"
19 #include "mock_fs.h"
20 #include "mock_node.h"
22 #include "nacl_io/filesystem.h"
23 #include "nacl_io/kernel_intercept.h"
24 #include "nacl_io/kernel_proxy.h"
25 #include "nacl_io/memfs/mem_fs.h"
26 #include "nacl_io/nacl_abi_dirent.h"
27 #include "nacl_io/osmman.h"
28 #include "nacl_io/ostime.h"
29 #include "nacl_io/path.h"
30 #include "nacl_io/typed_fs_factory.h"
32 using namespace nacl_io;
33 using namespace sdk_util;
35 using ::testing::_;
36 using ::testing::DoAll;
37 using ::testing::Invoke;
38 using ::testing::Return;
39 using ::testing::SaveArg;
40 using ::testing::SetArgPointee;
41 using ::testing::StrEq;
42 using ::testing::WithArgs;
44 namespace {
46 class KernelProxyTest_KernelProxy : public KernelProxy {
47 public:
48 Filesystem* RootFs() {
49 ScopedFilesystem fs;
50 Path path;
52 AcquireFsAndRelPath("/", &fs, &path);
53 return fs.get();
57 class KernelProxyTest : public ::testing::Test {
58 public:
59 KernelProxyTest() {}
61 void SetUp() {
62 ASSERT_EQ(0, ki_push_state_for_testing());
63 ASSERT_EQ(0, ki_init(&kp_));
64 // Unmount the passthrough FS and mount a memfs.
65 EXPECT_EQ(0, kp_.umount("/"));
66 EXPECT_EQ(0, kp_.mount("", "/", "memfs", 0, NULL));
69 void TearDown() { ki_uninit(); }
71 protected:
72 KernelProxyTest_KernelProxy kp_;
75 } // namespace
77 static int ki_fcntl_wrapper(int fd, int request, ...) {
78 va_list ap;
79 va_start(ap, request);
80 int rtn = ki_fcntl(fd, request, ap);
81 va_end(ap);
82 return rtn;
85 /**
86 * Test for fcntl commands F_SETFD and F_GETFD. This
87 * is tested here rather than in the mount_node tests
88 * since the fd flags are not stored in the kernel_handle
89 * or the filesystem node but directly in the FD mapping.
91 TEST_F(KernelProxyTest, Fcntl_GETFD) {
92 int fd = ki_open("/test", O_RDWR | O_CREAT, 0777);
93 ASSERT_NE(-1, fd);
95 // FD flags should start as zero.
96 ASSERT_EQ(0, ki_fcntl_wrapper(fd, F_GETFD));
98 // Check that setting FD_CLOEXEC works
99 int flags = FD_CLOEXEC;
100 ASSERT_EQ(0, ki_fcntl_wrapper(fd, F_SETFD, flags))
101 << "fcntl failed with: " << strerror(errno);
102 ASSERT_EQ(FD_CLOEXEC, ki_fcntl_wrapper(fd, F_GETFD));
104 // Check that setting invalid flag causes EINVAL
105 flags = FD_CLOEXEC + 1;
106 ASSERT_EQ(-1, ki_fcntl_wrapper(fd, F_SETFD, flags));
107 ASSERT_EQ(EINVAL, errno);
110 TEST_F(KernelProxyTest, FileLeak) {
111 const size_t buffer_size = 1024;
112 char filename[128];
113 int garbage[buffer_size];
115 MemFs* filesystem = (MemFs*)kp_.RootFs();
116 ScopedNode root;
118 ASSERT_EQ(0, filesystem->Open(Path("/"), O_RDONLY, &root));
119 ASSERT_EQ(0, root->ChildCount());
121 for (int file_num = 0; file_num < 4096; file_num++) {
122 sprintf(filename, "/foo%i.tmp", file_num++);
123 int fd = ki_open(filename, O_WRONLY | O_CREAT, 0777);
124 ASSERT_GT(fd, -1);
125 ASSERT_EQ(1, root->ChildCount());
126 ASSERT_EQ(buffer_size, ki_write(fd, garbage, buffer_size));
127 ki_close(fd);
128 ASSERT_EQ(0, ki_remove(filename));
130 ASSERT_EQ(0, root->ChildCount());
133 static bool g_handler_called = false;
134 static void sighandler(int) { g_handler_called = true; }
136 TEST_F(KernelProxyTest, Sigaction) {
137 struct sigaction action;
138 struct sigaction oaction;
139 memset(&action, 0, sizeof(action));
141 // Invalid signum
142 ASSERT_EQ(-1, ki_sigaction(-1, NULL, &oaction));
143 ASSERT_EQ(-1, ki_sigaction(SIGSTOP, NULL, &oaction));
144 ASSERT_EQ(EINVAL, errno);
146 // Get existing handler
147 memset(&oaction, 0, sizeof(oaction));
148 ASSERT_EQ(0, ki_sigaction(SIGINT, NULL, &oaction));
149 ASSERT_EQ(SIG_DFL, oaction.sa_handler);
151 // Attempt to set handler for unsupported signum
152 action.sa_handler = sighandler;
153 ASSERT_EQ(-1, ki_sigaction(SIGINT, &action, NULL));
154 ASSERT_EQ(EINVAL, errno);
156 // Attempt to set handler for supported signum
157 action.sa_handler = sighandler;
158 ASSERT_EQ(0, ki_sigaction(SIGWINCH, &action, NULL));
160 memset(&oaction, 0, sizeof(oaction));
161 ASSERT_EQ(0, ki_sigaction(SIGWINCH, NULL, &oaction));
162 ASSERT_EQ((sighandler_t*)sighandler, (sighandler_t*)oaction.sa_handler);
165 TEST_F(KernelProxyTest, KillSignals) {
166 // SIGSEGV can't be sent via kill(2)
167 ASSERT_EQ(-1, ki_kill(0, SIGSEGV)) << "kill(SEGV) failed to return an error";
168 ASSERT_EQ(EINVAL, errno) << "kill(SEGV) failed to set errno to EINVAL";
170 // Our implemenation should understand SIGWINCH
171 ASSERT_EQ(0, ki_kill(0, SIGWINCH)) << "kill(SIGWINCH) failed: " << errno;
173 // And USR1/USR2
174 ASSERT_EQ(0, ki_kill(0, SIGUSR1)) << "kill(SIGUSR1) failed: " << errno;
175 ASSERT_EQ(0, ki_kill(0, SIGUSR2)) << "kill(SIGUSR2) failed: " << errno;
178 TEST_F(KernelProxyTest, KillPIDValues) {
179 // Any PID other than 0, -1 and getpid() should yield ESRCH
180 // since there is only one valid process under NaCl
181 int mypid = getpid();
182 ASSERT_EQ(0, ki_kill(0, SIGWINCH));
183 ASSERT_EQ(0, ki_kill(-1, SIGWINCH));
184 ASSERT_EQ(0, ki_kill(mypid, SIGWINCH));
186 // Don't use mypid + 1 since getpid() actually returns -1
187 // when the IRT interface is missing (e.g. within chrome),
188 // and 0 is always a valid PID when calling kill().
189 int invalid_pid = mypid + 10;
190 ASSERT_EQ(-1, ki_kill(invalid_pid, SIGWINCH));
191 ASSERT_EQ(ESRCH, errno);
194 TEST_F(KernelProxyTest, SignalValues) {
195 ASSERT_EQ(ki_signal(SIGSEGV, sighandler), SIG_ERR)
196 << "registering SEGV handler didn't fail";
197 ASSERT_EQ(errno, EINVAL) << "signal(SEGV) failed to set errno to EINVAL";
199 ASSERT_EQ(ki_signal(-1, sighandler), SIG_ERR)
200 << "registering handler for invalid signal didn't fail";
201 ASSERT_EQ(errno, EINVAL) << "signal(-1) failed to set errno to EINVAL";
204 TEST_F(KernelProxyTest, SignalHandlerValues) {
205 // Unsupported signal.
206 ASSERT_NE(SIG_ERR, ki_signal(SIGSEGV, SIG_DFL));
207 ASSERT_EQ(SIG_ERR, ki_signal(SIGSEGV, SIG_IGN));
208 ASSERT_EQ(SIG_ERR, ki_signal(SIGSEGV, sighandler));
210 // Supported signal.
211 ASSERT_NE(SIG_ERR, ki_signal(SIGWINCH, SIG_DFL));
212 ASSERT_NE(SIG_ERR, ki_signal(SIGWINCH, SIG_IGN));
213 ASSERT_NE(SIG_ERR, ki_signal(SIGWINCH, sighandler));
216 TEST_F(KernelProxyTest, SignalSigwinch) {
217 g_handler_called = false;
219 // Register WINCH handler
220 sighandler_t newsig = sighandler;
221 sighandler_t oldsig = ki_signal(SIGWINCH, newsig);
222 ASSERT_NE(oldsig, SIG_ERR);
224 // Send signal.
225 ki_kill(0, SIGWINCH);
227 // Verify that handler was called
228 EXPECT_TRUE(g_handler_called);
230 // Restore existing handler
231 oldsig = ki_signal(SIGWINCH, oldsig);
233 // Verify the our newsig was returned as previous handler
234 ASSERT_EQ(oldsig, newsig);
237 TEST_F(KernelProxyTest, Rename) {
238 // Create a dummy file
239 int file1 = ki_open("/test1.txt", O_RDWR | O_CREAT, 0777);
240 ASSERT_GT(file1, -1);
241 ASSERT_EQ(0, ki_close(file1));
243 // Test the renaming works
244 ASSERT_EQ(0, ki_rename("/test1.txt", "/test2.txt"));
246 // Test that renaming across mount points fails
247 ASSERT_EQ(0, ki_mount("", "/foo", "memfs", 0, ""));
248 ASSERT_EQ(-1, ki_rename("/test2.txt", "/foo/test2.txt"));
249 ASSERT_EQ(EXDEV, errno);
252 TEST_F(KernelProxyTest, WorkingDirectory) {
253 char text[1024];
255 text[0] = 0;
256 ki_getcwd(text, sizeof(text));
257 EXPECT_STREQ("/", text);
259 char* alloc = ki_getwd(NULL);
260 EXPECT_EQ((char*)NULL, alloc);
261 EXPECT_EQ(EFAULT, errno);
263 text[0] = 0;
264 alloc = ki_getwd(text);
265 EXPECT_STREQ("/", alloc);
267 EXPECT_EQ(-1, ki_chdir("/foo"));
268 EXPECT_EQ(ENOENT, errno);
270 EXPECT_EQ(0, ki_chdir("/"));
272 EXPECT_EQ(0, ki_mkdir("/foo", S_IRUSR | S_IWUSR));
273 EXPECT_EQ(-1, ki_mkdir("/foo", S_IRUSR | S_IWUSR));
274 EXPECT_EQ(EEXIST, errno);
276 memset(text, 0, sizeof(text));
277 EXPECT_EQ(0, ki_chdir("foo"));
278 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
279 EXPECT_STREQ("/foo", text);
281 memset(text, 0, sizeof(text));
282 EXPECT_EQ(-1, ki_chdir("foo"));
283 EXPECT_EQ(ENOENT, errno);
284 EXPECT_EQ(0, ki_chdir(".."));
285 EXPECT_EQ(0, ki_chdir("/foo"));
286 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
287 EXPECT_STREQ("/foo", text);
290 TEST_F(KernelProxyTest, FDPathMapping) {
291 char text[1024];
293 int fd1, fd2, fd3, fd4, fd5;
295 EXPECT_EQ(0, ki_mkdir("/foo", S_IRUSR | S_IWUSR));
296 EXPECT_EQ(0, ki_mkdir("/foo/bar", S_IRUSR | S_IWUSR));
297 EXPECT_EQ(0, ki_mkdir("/example", S_IRUSR | S_IWUSR));
298 ki_chdir("/foo");
300 fd1 = ki_open("/example", O_RDONLY, 0);
301 EXPECT_NE(-1, fd1);
302 EXPECT_EQ(ki_fchdir(fd1), 0);
303 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
304 EXPECT_STREQ("/example", text);
306 EXPECT_EQ(0, ki_chdir("/foo"));
307 fd2 = ki_open("../example", O_RDONLY, 0);
308 EXPECT_NE(-1, fd2);
309 EXPECT_EQ(0, ki_fchdir(fd2));
310 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
311 EXPECT_STREQ("/example", text);
313 EXPECT_EQ(0, ki_chdir("/foo"));
314 fd3 = ki_open("../test", O_CREAT | O_RDWR, 0777);
315 EXPECT_NE(-1, fd3);
316 EXPECT_EQ(-1, ki_fchdir(fd3));
317 EXPECT_EQ(ENOTDIR, errno);
319 EXPECT_EQ(0, ki_chdir("/foo"));
320 fd4 = ki_open("bar", O_RDONLY, 0);
321 EXPECT_EQ(0, ki_fchdir(fd4));
322 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
323 EXPECT_STREQ("/foo/bar", text);
324 EXPECT_EQ(0, ki_chdir("/example"));
325 EXPECT_EQ(0, ki_fchdir(fd4));
326 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
327 EXPECT_STREQ("/foo/bar", text);
329 EXPECT_EQ(0, ki_chdir("/example"));
330 fd5 = ki_dup(fd4);
331 ASSERT_GT(fd5, -1);
332 ASSERT_NE(fd4, fd5);
333 EXPECT_EQ(0, ki_fchdir(fd5));
334 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
335 EXPECT_STREQ("/foo/bar", text);
337 fd5 = 123;
339 EXPECT_EQ(0, ki_chdir("/example"));
340 EXPECT_EQ(fd5, ki_dup2(fd4, fd5));
341 EXPECT_EQ(0, ki_fchdir(fd5));
342 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
343 EXPECT_STREQ("/foo/bar", text);
346 TEST_F(KernelProxyTest, BasicReadWrite) {
347 char text[1024];
348 int fd1, fd2, fd3;
349 int len;
351 // Fail to delete non existant "/foo"
352 EXPECT_EQ(-1, ki_rmdir("/foo"));
353 EXPECT_EQ(ENOENT, errno);
355 // Create "/foo"
356 EXPECT_EQ(0, ki_mkdir("/foo", S_IRUSR | S_IWUSR));
357 EXPECT_EQ(-1, ki_mkdir("/foo", S_IRUSR | S_IWUSR));
358 EXPECT_EQ(EEXIST, errno);
360 // Delete "/foo"
361 EXPECT_EQ(0, ki_rmdir("/foo"));
363 // Recreate "/foo"
364 EXPECT_EQ(0, ki_mkdir("/foo", S_IRUSR | S_IWUSR));
366 // Fail to open "/foo/bar"
367 EXPECT_EQ(-1, ki_open("/foo/bar", O_RDONLY, 0));
368 EXPECT_EQ(ENOENT, errno);
370 // Create bar "/foo/bar"
371 fd1 = ki_open("/foo/bar", O_RDWR | O_CREAT, 0777);
372 ASSERT_NE(-1, fd1);
374 // Open (optionally create) bar "/foo/bar"
375 fd2 = ki_open("/foo/bar", O_RDWR | O_CREAT, 0777);
376 ASSERT_NE(-1, fd2);
378 // Fail to exclusively create bar "/foo/bar"
379 EXPECT_EQ(-1, ki_open("/foo/bar", O_RDONLY | O_CREAT | O_EXCL, 0777));
380 EXPECT_EQ(EEXIST, errno);
382 // Write hello and world to same node with different descriptors
383 // so that we overwrite each other
384 EXPECT_EQ(5, ki_write(fd2, "WORLD", 5));
385 EXPECT_EQ(5, ki_write(fd1, "HELLO", 5));
387 fd3 = ki_open("/foo/bar", O_RDONLY, 0);
388 ASSERT_NE(-1, fd3);
390 len = ki_read(fd3, text, sizeof(text));
391 ASSERT_EQ(5, len);
392 text[len] = 0;
393 EXPECT_STREQ("HELLO", text);
394 EXPECT_EQ(0, ki_close(fd1));
395 EXPECT_EQ(0, ki_close(fd2));
397 fd1 = ki_open("/foo/bar", O_WRONLY | O_APPEND, 0);
398 ASSERT_NE(-1, fd1);
399 EXPECT_EQ(5, ki_write(fd1, "WORLD", 5));
401 len = ki_read(fd3, text, sizeof(text));
402 ASSERT_EQ(5, len);
403 text[len] = 0;
404 EXPECT_STREQ("WORLD", text);
406 fd2 = ki_open("/foo/bar", O_RDONLY, 0);
407 ASSERT_NE(-1, fd2);
408 len = ki_read(fd2, text, sizeof(text));
409 if (len > 0)
410 text[len] = 0;
411 EXPECT_EQ(10, len);
412 EXPECT_STREQ("HELLOWORLD", text);
415 TEST_F(KernelProxyTest, FTruncate) {
416 char text[1024];
417 int fd1, fd2;
419 // Open a file write only, write some text, then test that using a
420 // separate file descriptor pointing to it that it is correctly
421 // truncated at a specified number of bytes (2).
422 fd1 = ki_open("/trunc", O_WRONLY | O_CREAT, 0777);
423 ASSERT_NE(-1, fd1);
424 fd2 = ki_open("/trunc", O_RDONLY, 0);
425 ASSERT_NE(-1, fd2);
426 EXPECT_EQ(5, ki_write(fd1, "HELLO", 5));
427 EXPECT_EQ(0, ki_ftruncate(fd1, 2));
428 // Verify the remaining file (using fd2, opened pre-truncation) is
429 // only 2 bytes in length.
430 EXPECT_EQ(2, ki_read(fd2, text, sizeof(text)));
431 EXPECT_EQ(0, ki_close(fd1));
432 EXPECT_EQ(0, ki_close(fd2));
434 // Truncate should fail if the file is not writable.
435 EXPECT_EQ(0, ki_chmod("/trunc", 0444));
436 fd2 = ki_open("/trunc", O_RDONLY, 0);
437 ASSERT_NE(-1, fd2);
438 EXPECT_EQ(-1, ki_ftruncate(fd2, 0));
439 EXPECT_EQ(EACCES, errno);
442 TEST_F(KernelProxyTest, Truncate) {
443 char text[1024];
444 int fd1;
446 // Open a file write only, write some text, then test that by
447 // referring to it by its path and truncating it we correctly truncate
448 // it at a specified number of bytes (2).
449 fd1 = ki_open("/trunc", O_WRONLY | O_CREAT, 0777);
450 ASSERT_NE(-1, fd1);
451 EXPECT_EQ(5, ki_write(fd1, "HELLO", 5));
452 EXPECT_EQ(0, ki_close(fd1));
453 EXPECT_EQ(0, ki_truncate("/trunc", 2));
454 // Verify the text is only 2 bytes long with new file descriptor.
455 fd1 = ki_open("/trunc", O_RDONLY, 0);
456 ASSERT_NE(-1, fd1);
457 EXPECT_EQ(2, ki_read(fd1, text, sizeof(text)));
458 EXPECT_EQ(0, ki_close(fd1));
460 // Truncate should fail if the file is not writable.
461 EXPECT_EQ(0, ki_chmod("/trunc", 0444));
462 EXPECT_EQ(-1, ki_truncate("/trunc", 0));
463 EXPECT_EQ(EACCES, errno);
466 TEST_F(KernelProxyTest, Lseek) {
467 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
468 ASSERT_GT(fd, -1);
469 ASSERT_EQ(9, ki_write(fd, "Some text", 9));
471 ASSERT_EQ(9, ki_lseek(fd, 0, SEEK_CUR));
472 ASSERT_EQ(9, ki_lseek(fd, 0, SEEK_END));
473 ASSERT_EQ(-1, ki_lseek(fd, -1, SEEK_SET));
474 ASSERT_EQ(EINVAL, errno);
476 // Seek past end of file.
477 ASSERT_EQ(13, ki_lseek(fd, 13, SEEK_SET));
478 char buffer[4];
479 memset(&buffer[0], 0xfe, 4);
480 ASSERT_EQ(9, ki_lseek(fd, -4, SEEK_END));
481 ASSERT_EQ(9, ki_lseek(fd, 0, SEEK_CUR));
482 ASSERT_EQ(4, ki_read(fd, &buffer[0], 4));
483 ASSERT_EQ(0, memcmp("\0\0\0\0", buffer, 4));
486 TEST_F(KernelProxyTest, CloseTwice) {
487 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
488 ASSERT_GT(fd, -1);
490 EXPECT_EQ(9, ki_write(fd, "Some text", 9));
492 int fd2 = ki_dup(fd);
493 ASSERT_GT(fd2, -1);
495 EXPECT_EQ(0, ki_close(fd));
496 EXPECT_EQ(0, ki_close(fd2));
499 TEST_F(KernelProxyTest, Dup) {
500 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
501 ASSERT_GT(fd, -1);
503 int dup_fd = ki_dup(fd);
504 ASSERT_NE(-1, dup_fd);
506 ASSERT_EQ(9, ki_write(fd, "Some text", 9));
507 ASSERT_EQ(9, ki_lseek(fd, 0, SEEK_CUR));
508 ASSERT_EQ(9, ki_lseek(dup_fd, 0, SEEK_CUR));
510 int dup2_fd = 123;
511 ASSERT_EQ(dup2_fd, ki_dup2(fd, dup2_fd));
512 ASSERT_EQ(9, ki_lseek(dup2_fd, 0, SEEK_CUR));
514 int new_fd = ki_open("/bar", O_CREAT | O_RDWR, 0777);
516 ASSERT_EQ(fd, ki_dup2(new_fd, fd));
517 // fd, new_fd -> "/bar"
518 // dup_fd, dup2_fd -> "/foo"
520 // We should still be able to write to dup_fd (i.e. it should not be closed).
521 ASSERT_EQ(4, ki_write(dup_fd, "more", 4));
523 ASSERT_EQ(0, ki_close(dup2_fd));
524 // fd, new_fd -> "/bar"
525 // dup_fd -> "/foo"
527 ASSERT_EQ(dup_fd, ki_dup2(fd, dup_fd));
528 // fd, new_fd, dup_fd -> "/bar"
531 TEST_F(KernelProxyTest, DescriptorDup2Dance) {
532 // Open a file to a get a descriptor to copy for this test.
533 // The test makes the assumption at all descriptors
534 // open by default are contiguous starting from zero.
535 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
536 ASSERT_GT(fd, -1);
538 // The comment above each statement below tracks which descriptors,
539 // starting from fd are currently allocated.
540 // Descriptors marked with an 'x' are allocated.
542 // (fd) (fd + 1) (fd + 2)
543 // x
544 ASSERT_EQ(fd + 1, ki_dup2(fd, fd + 1));
545 // (fd) (fd + 1) (fd + 2)
546 // x x
547 ASSERT_EQ(0, ki_close(fd + 1));
548 // (fd) (fd + 1) (fd + 2)
549 // x
550 ASSERT_EQ(fd + 1, ki_dup2(fd, fd + 1));
551 // (fd) (fd + 1) (fd + 2)
552 // x x
553 ASSERT_EQ(fd + 2, ki_dup(fd));
554 // (fd) (fd + 1) (fd + 2)
555 // x x x
556 ASSERT_EQ(0, ki_close(fd + 2));
557 // (fd) (fd + 1) (fd + 2)
558 // x x
559 ASSERT_EQ(0, ki_close(fd + 1));
560 // (fd) (fd + 1) (fd + 2)
561 // x
562 ASSERT_EQ(0, ki_close(fd));
565 TEST_F(KernelProxyTest, Dup2Negative) {
566 // Open a file to a get a descriptor to copy for this test.
567 // The test makes the assumption at all descriptors
568 // open by default are contiguous starting from zero.
569 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
570 ASSERT_GT(fd, -1);
572 // Attempt to dup2 to an invalid descriptor.
573 ASSERT_EQ(-1, ki_dup2(fd, -12));
574 EXPECT_EQ(EBADF, errno);
575 ASSERT_EQ(0, ki_close(fd));
578 TEST_F(KernelProxyTest, DescriptorAllocationConsistency) {
579 // Check that the descriptor free list returns the expected ones,
580 // as the order is mandated by POSIX.
582 // Open a file to a get a descriptor to copy for this test.
583 // The test makes the assumption at all descriptors
584 // open by default are contiguous starting from zero.
585 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
586 ASSERT_GT(fd, -1);
588 // The next descriptor allocated should follow the first.
589 int dup_fd = ki_dup(fd);
590 ASSERT_EQ(fd + 1, dup_fd);
592 // Allocate a high descriptor number.
593 ASSERT_EQ(100, ki_dup2(fd, 100));
595 // The next descriptor allocate should still come 2 places
596 // after the first.
597 int dup_fd2 = ki_dup(fd);
598 ASSERT_EQ(fd + 2, dup_fd2);
601 TEST_F(KernelProxyTest, Lstat) {
602 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
603 ASSERT_GT(fd, -1);
604 ASSERT_EQ(0, ki_mkdir("/bar", S_IRUSR | S_IWUSR));
606 struct stat buf;
607 EXPECT_EQ(0, ki_lstat("/foo", &buf));
608 EXPECT_EQ(0, buf.st_size);
609 EXPECT_TRUE(S_ISREG(buf.st_mode));
611 EXPECT_EQ(0, ki_lstat("/bar", &buf));
612 EXPECT_GT(buf.st_size, 0);
613 EXPECT_TRUE(S_ISDIR(buf.st_mode));
615 EXPECT_EQ(-1, ki_lstat("/no-such-file", &buf));
616 EXPECT_EQ(ENOENT, errno);
618 // Still legal to stat a file that is write-only.
619 EXPECT_EQ(0, ki_chmod("/foo", 0222));
620 EXPECT_EQ(0, ki_lstat("/foo", &buf));
623 TEST_F(KernelProxyTest, Chmod) {
624 ASSERT_EQ(-1, ki_chmod("/foo", 0222));
625 ASSERT_EQ(errno, ENOENT);
627 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0770);
628 ASSERT_GT(fd, -1);
630 struct stat buf;
631 ASSERT_EQ(0, ki_stat("/foo", &buf));
632 ASSERT_EQ(0770, buf.st_mode & 0777);
634 ASSERT_EQ(0, ki_chmod("/foo", 0222));
635 ASSERT_EQ(0, ki_stat("/foo", &buf));
636 ASSERT_EQ(0222, buf.st_mode & 0777);
638 // Check that passing mode bits other than permissions
639 // is ignored.
640 ASSERT_EQ(0, ki_chmod("/foo", S_IFBLK | 0222));
641 ASSERT_EQ(0, ki_stat("/foo", &buf));
642 EXPECT_TRUE(S_ISREG(buf.st_mode));
643 ASSERT_EQ(0222, buf.st_mode & 0777);
646 TEST_F(KernelProxyTest, Fchmod) {
647 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0770);
648 ASSERT_GT(fd, -1);
650 struct stat buf;
651 ASSERT_EQ(0, ki_stat("/foo", &buf));
652 ASSERT_EQ(0770, buf.st_mode & 0777);
654 ASSERT_EQ(0, ki_fchmod(fd, 0222));
655 ASSERT_EQ(0, ki_stat("/foo", &buf));
656 ASSERT_EQ(0222, buf.st_mode & 0777);
658 // Check that passing mode bits other than permissions
659 // is ignored.
660 ASSERT_EQ(0, ki_fchmod(fd, S_IFBLK | 0222));
661 ASSERT_EQ(0, ki_stat("/foo", &buf));
662 EXPECT_TRUE(S_ISREG(buf.st_mode));
663 ASSERT_EQ(0222, buf.st_mode & 0777);
666 TEST_F(KernelProxyTest, OpenDirectory) {
667 // Opening a directory for read should succeed.
668 int fd = ki_open("/", O_RDONLY, 0);
669 ASSERT_GT(fd, -1);
671 // Opening a directory for write should fail.
672 EXPECT_EQ(-1, ki_open("/", O_RDWR, 0));
673 EXPECT_EQ(errno, EISDIR);
674 EXPECT_EQ(-1, ki_open("/", O_WRONLY, 0));
675 EXPECT_EQ(errno, EISDIR);
678 TEST_F(KernelProxyTest, OpenWithMode) {
679 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0723);
680 ASSERT_GT(fd, -1);
682 struct stat buf;
683 EXPECT_EQ(0, ki_lstat("/foo", &buf));
684 EXPECT_EQ(0723, buf.st_mode & 0777);
687 TEST_F(KernelProxyTest, CreateWronlyWithReadOnlyMode) {
688 int fd = ki_open("/foo", O_CREAT | O_WRONLY, 0444);
689 ASSERT_GT(fd, -1);
692 TEST_F(KernelProxyTest, UseAfterClose) {
693 int fd = ki_open("/dummy", O_CREAT | O_WRONLY, 0777);
694 ASSERT_GT(fd, -1);
695 EXPECT_EQ(5, ki_write(fd, "hello", 5));
696 EXPECT_EQ(0, ki_close(fd));
697 EXPECT_EQ(-1, ki_write(fd, "hello", 5));
698 EXPECT_EQ(EBADF, errno);
701 TEST_F(KernelProxyTest, Utimes) {
702 struct timeval times[2];
703 times[0].tv_sec = 1000;
704 times[0].tv_usec = 2000;
705 times[1].tv_sec = 3000;
706 times[1].tv_usec = 4000;
708 int fd = ki_open("/dummy", O_CREAT | O_WRONLY, 0222);
709 ASSERT_GT(fd, -1);
710 EXPECT_EQ(0, ki_close(fd));
712 // utime should work if the file is write-only.
713 EXPECT_EQ(0, ki_utimes("/dummy", times));
715 // utime should work on directories (which can never be opened for write)
716 EXPECT_EQ(0, ki_utimes("/", times));
718 // or if the file is read-only.
719 EXPECT_EQ(0, ki_chmod("/dummy", 0444));
720 EXPECT_EQ(0, ki_utimes("/dummy", times));
722 // times can be NULL. In that case the access/mod times will be set to the
723 // current time.
724 struct timeval tm;
725 EXPECT_EQ(0, gettimeofday(&tm, NULL));
727 EXPECT_EQ(0, ki_utimes("/dummy", NULL));
728 struct stat buf;
729 EXPECT_EQ(0, ki_stat("/dummy", &buf));
731 // We just want to check if st_atime >= tm. This is true if atime seconds > tm
732 // seconds (in which case the nanoseconds are irrelevant), or if the seconds
733 // are equal, then this is true if atime nanoseconds >= tm microseconds.
734 EXPECT_TRUE(
735 buf.st_atime > tm.tv_sec ||
736 (buf.st_atime == tm.tv_sec && buf.st_atimensec >= tm.tv_usec * 1000));
737 EXPECT_TRUE(
738 buf.st_mtime > tm.tv_sec ||
739 (buf.st_mtime == tm.tv_sec && buf.st_mtimensec >= tm.tv_usec * 1000));
742 TEST_F(KernelProxyTest, Utime) {
743 struct utimbuf times;
744 times.actime = 1000;
745 times.modtime = 2000;
747 int fd = ki_open("/dummy", O_CREAT | O_WRONLY, 0222);
748 ASSERT_GT(fd, -1);
749 EXPECT_EQ(0, ki_close(fd));
751 // utime should work if the file is write-only.
752 EXPECT_EQ(0, ki_utime("/dummy", &times));
754 // or if the file is read-only.
755 EXPECT_EQ(0, ki_chmod("/dummy", 0444));
756 EXPECT_EQ(0, ki_utime("/dummy", &times));
758 // times can be NULL. In that case the access/mod times will be set to the
759 // current time.
760 struct timeval tm;
761 EXPECT_EQ(0, gettimeofday(&tm, NULL));
763 EXPECT_EQ(0, ki_utime("/dummy", NULL));
764 struct stat buf;
765 EXPECT_EQ(0, ki_stat("/dummy", &buf));
767 // We just want to check if st_atime >= tm. This is true if atime seconds > tm
768 // seconds (in which case the nanoseconds are irrelevant), or if the seconds
769 // are equal, then this is true if atime nanoseconds >= tm microseconds.
770 EXPECT_TRUE(
771 buf.st_atime > tm.tv_sec ||
772 (buf.st_atime == tm.tv_sec && buf.st_atimensec >= tm.tv_usec * 1000));
773 EXPECT_TRUE(
774 buf.st_mtime > tm.tv_sec ||
775 (buf.st_mtime == tm.tv_sec && buf.st_mtimensec >= tm.tv_usec * 1000));
778 TEST_F(KernelProxyTest, Umask) {
779 mode_t oldmask = ki_umask(0222);
780 EXPECT_EQ(0, oldmask);
782 int fd = ki_open("/foo", O_CREAT | O_RDONLY, 0666);
783 ASSERT_GT(fd, -1);
784 ki_close(fd);
786 EXPECT_EQ(0, ki_mkdir("/dir", 0777));
788 struct stat buf;
789 EXPECT_EQ(0, ki_stat("/foo", &buf));
790 EXPECT_EQ(0444, buf.st_mode & 0777);
792 EXPECT_EQ(0, ki_stat("/dir", &buf));
793 EXPECT_EQ(0555, buf.st_mode & 0777);
795 EXPECT_EQ(0222, ki_umask(0));
798 namespace {
800 StringMap_t g_string_map;
801 bool g_fs_ioctl_called;
802 int g_fs_dev;
804 class KernelProxyMountTest_Filesystem : public MemFs {
805 public:
806 virtual Error Init(const FsInitArgs& args) {
807 MemFs::Init(args);
809 g_string_map = args.string_map;
810 g_fs_dev = args.dev;
812 if (g_string_map.find("false") != g_string_map.end())
813 return EINVAL;
814 return 0;
817 virtual Error Filesystem_VIoctl(int request, va_list arglist) {
818 g_fs_ioctl_called = true;
819 return 0;
822 friend class TypedFsFactory<KernelProxyMountTest_Filesystem>;
825 class KernelProxyMountTest_KernelProxy : public KernelProxy {
826 virtual Error Init(PepperInterface* ppapi) {
827 KernelProxy::Init(NULL);
828 factories_["initfs"] = new TypedFsFactory<KernelProxyMountTest_Filesystem>;
829 return 0;
833 class KernelProxyMountTest : public ::testing::Test {
834 public:
835 KernelProxyMountTest() {}
837 void SetUp() {
838 g_string_map.clear();
839 g_fs_dev = -1;
840 g_fs_ioctl_called = false;
842 ASSERT_EQ(0, ki_push_state_for_testing());
843 ASSERT_EQ(0, ki_init(&kp_));
846 void TearDown() {
847 g_string_map.clear();
848 ki_uninit();
851 protected:
852 KernelProxyMountTest_KernelProxy kp_;
855 // Helper function for calling ki_ioctl without having
856 // to construct a va_list.
857 int ki_ioctl_wrapper(int fd, int request, ...) {
858 va_list ap;
859 va_start(ap, request);
860 int rtn = ki_ioctl(fd, request, ap);
861 va_end(ap);
862 return rtn;
865 } // namespace
867 TEST_F(KernelProxyMountTest, MountInit) {
868 int res1 = ki_mount("/", "/mnt1", "initfs", 0, "false,foo=bar");
870 EXPECT_EQ("bar", g_string_map["foo"]);
871 EXPECT_EQ(-1, res1);
872 EXPECT_EQ(EINVAL, errno);
874 int res2 = ki_mount("/", "/mnt2", "initfs", 0, "true,bar=foo,x=y");
875 EXPECT_NE(-1, res2);
876 EXPECT_EQ("y", g_string_map["x"]);
879 TEST_F(KernelProxyMountTest, MountAndIoctl) {
880 ASSERT_EQ(0, ki_mount("/", "/mnt1", "initfs", 0, ""));
881 ASSERT_NE(-1, g_fs_dev);
883 char path[100];
884 snprintf(path, 100, "dev/fs/%d", g_fs_dev);
886 int fd = ki_open(path, O_RDONLY, 0);
887 ASSERT_GT(fd, -1);
889 EXPECT_EQ(0, ki_ioctl_wrapper(fd, 0xdeadbeef));
890 EXPECT_EQ(true, g_fs_ioctl_called);
893 static void mount_callback(const char* source,
894 const char* target,
895 const char* filesystemtype,
896 unsigned long mountflags,
897 const void* data,
898 dev_t dev,
899 void* user_data) {
900 EXPECT_STREQ("/", source);
901 EXPECT_STREQ("/mnt1", target);
902 EXPECT_STREQ("initfs", filesystemtype);
903 EXPECT_EQ(0, mountflags);
904 EXPECT_STREQ("", (const char*) data);
905 EXPECT_EQ(g_fs_dev, dev);
907 bool* callback_called = static_cast<bool*>(user_data);
908 *callback_called = true;
911 TEST_F(KernelProxyMountTest, MountCallback) {
912 bool callback_called = false;
913 kp_.SetMountCallback(&mount_callback, &callback_called);
914 ASSERT_EQ(0, ki_mount("/", "/mnt1", "initfs", 0, ""));
915 ASSERT_NE(-1, g_fs_dev);
916 EXPECT_EQ(true, callback_called);
919 namespace {
921 int g_MMapCount = 0;
923 class KernelProxyMMapTest_Node : public Node {
924 public:
925 KernelProxyMMapTest_Node(Filesystem* filesystem)
926 : Node(filesystem), node_mmap_count_(0) {
927 EXPECT_EQ(0, Init(0));
930 virtual Error MMap(void* addr,
931 size_t length,
932 int prot,
933 int flags,
934 size_t offset,
935 void** out_addr) {
936 node_mmap_count_++;
937 switch (g_MMapCount++) {
938 case 0:
939 *out_addr = reinterpret_cast<void*>(0x1000);
940 break;
941 case 1:
942 *out_addr = reinterpret_cast<void*>(0x2000);
943 break;
944 case 2:
945 *out_addr = reinterpret_cast<void*>(0x3000);
946 break;
947 default:
948 return EPERM;
951 return 0;
954 private:
955 int node_mmap_count_;
958 class KernelProxyMMapTest_Filesystem : public Filesystem {
959 public:
960 virtual Error OpenWithMode(const Path& path, int open_flags,
961 mode_t mode, ScopedNode* out_node) {
962 out_node->reset(new KernelProxyMMapTest_Node(this));
963 return 0;
966 virtual Error OpenResource(const Path& path, ScopedNode* out_node) {
967 out_node->reset(NULL);
968 return ENOSYS;
970 virtual Error Unlink(const Path& path) { return ENOSYS; }
971 virtual Error Mkdir(const Path& path, int permissions) { return ENOSYS; }
972 virtual Error Rmdir(const Path& path) { return ENOSYS; }
973 virtual Error Remove(const Path& path) { return ENOSYS; }
974 virtual Error Rename(const Path& path, const Path& newpath) { return ENOSYS; }
976 friend class TypedFsFactory<KernelProxyMMapTest_Filesystem>;
979 class KernelProxyMMapTest_KernelProxy : public KernelProxy {
980 virtual Error Init(PepperInterface* ppapi) {
981 KernelProxy::Init(NULL);
982 factories_["mmapfs"] = new TypedFsFactory<KernelProxyMMapTest_Filesystem>;
983 return 0;
987 class KernelProxyMMapTest : public ::testing::Test {
988 public:
989 KernelProxyMMapTest() {}
991 void SetUp() {
992 ASSERT_EQ(0, ki_push_state_for_testing());
993 ASSERT_EQ(0, ki_init(&kp_));
996 void TearDown() { ki_uninit(); }
998 private:
999 KernelProxyMMapTest_KernelProxy kp_;
1002 } // namespace
1004 TEST_F(KernelProxyMMapTest, MMap) {
1005 ASSERT_EQ(0, ki_umount("/"));
1006 ASSERT_EQ(0, ki_mount("", "/", "mmapfs", 0, NULL));
1007 int fd = ki_open("/file", O_RDWR | O_CREAT, 0777);
1008 ASSERT_NE(-1, fd);
1010 void* addr1 = ki_mmap(NULL, 0x800, PROT_READ, MAP_PRIVATE, fd, 0);
1011 ASSERT_EQ(reinterpret_cast<void*>(0x1000), addr1);
1012 ASSERT_EQ(1, g_MMapCount);
1014 void* addr2 = ki_mmap(NULL, 0x800, PROT_READ, MAP_PRIVATE, fd, 0);
1015 ASSERT_EQ(reinterpret_cast<void*>(0x2000), addr2);
1016 ASSERT_EQ(2, g_MMapCount);
1018 void* addr3 = ki_mmap(NULL, 0x800, PROT_READ, MAP_PRIVATE, fd, 0);
1019 ASSERT_EQ(reinterpret_cast<void*>(0x3000), addr3);
1020 ASSERT_EQ(3, g_MMapCount);
1022 ki_close(fd);
1024 // We no longer track mmap'd regions, so munmap is a no-op.
1025 ASSERT_EQ(0, ki_munmap(reinterpret_cast<void*>(0x1000), 0x2800));
1026 // We don't track regions, so the mmap count hasn't changed.
1027 ASSERT_EQ(3, g_MMapCount);
1030 namespace {
1032 class SingletonFsFactory : public FsFactory {
1033 public:
1034 SingletonFsFactory(const ScopedFilesystem& filesystem) : mount_(filesystem) {}
1036 virtual Error CreateFilesystem(const FsInitArgs& args,
1037 ScopedFilesystem* out_fs) {
1038 *out_fs = mount_;
1039 return 0;
1042 private:
1043 ScopedFilesystem mount_;
1046 class KernelProxyErrorTest_KernelProxy : public KernelProxy {
1047 public:
1048 KernelProxyErrorTest_KernelProxy() : fs_(new MockFs) {}
1050 virtual Error Init(PepperInterface* ppapi) {
1051 KernelProxy::Init(ppapi);
1052 factories_["testfs"] = new SingletonFsFactory(fs_);
1054 EXPECT_CALL(*fs_, Destroy()).Times(1);
1055 return 0;
1058 ScopedRef<MockFs> fs() { return fs_; }
1060 private:
1061 ScopedRef<MockFs> fs_;
1064 class KernelProxyErrorTest : public ::testing::Test {
1065 public:
1066 KernelProxyErrorTest() {}
1068 void SetUp() {
1069 ASSERT_EQ(0, ki_push_state_for_testing());
1070 ASSERT_EQ(0, ki_init(&kp_));
1071 // Unmount the passthrough FS and mount a testfs.
1072 EXPECT_EQ(0, kp_.umount("/"));
1073 EXPECT_EQ(0, kp_.mount("", "/", "testfs", 0, NULL));
1076 void TearDown() { ki_uninit(); }
1078 ScopedRef<MockFs> fs() { return kp_.fs(); }
1080 private:
1081 KernelProxyErrorTest_KernelProxy kp_;
1084 } // namespace
1086 TEST_F(KernelProxyErrorTest, WriteError) {
1087 ScopedRef<MockFs> mock_fs(fs());
1088 ScopedRef<MockNode> mock_node(new MockNode(&*mock_fs));
1089 EXPECT_CALL(*mock_fs, OpenWithMode(_, _, _, _))
1090 .WillOnce(DoAll(SetArgPointee<3>(mock_node), Return(0)));
1092 EXPECT_CALL(*mock_node, Write(_, _, _, _))
1093 .WillOnce(DoAll(SetArgPointee<3>(0), // Wrote 0 bytes.
1094 Return(1234))); // Returned error 1234.
1096 EXPECT_CALL(*mock_node, IsaDir()).Times(1);
1097 EXPECT_CALL(*mock_node, Destroy()).Times(1);
1099 int fd = ki_open("/dummy", O_WRONLY, 0);
1100 EXPECT_NE(0, fd);
1102 char buf[20];
1103 EXPECT_EQ(-1, ki_write(fd, &buf[0], 20));
1104 // The Filesystem should be able to return whatever error it wants and have it
1105 // propagate through.
1106 EXPECT_EQ(1234, errno);
1109 TEST_F(KernelProxyErrorTest, ReadError) {
1110 ScopedRef<MockFs> mock_fs(fs());
1111 ScopedRef<MockNode> mock_node(new MockNode(&*mock_fs));
1112 EXPECT_CALL(*mock_fs, OpenWithMode(_, _, _, _))
1113 .WillOnce(DoAll(SetArgPointee<3>(mock_node), Return(0)));
1115 EXPECT_CALL(*mock_node, Read(_, _, _, _))
1116 .WillOnce(DoAll(SetArgPointee<3>(0), // Read 0 bytes.
1117 Return(1234))); // Returned error 1234.
1119 EXPECT_CALL(*mock_node, Destroy()).Times(1);
1121 int fd = ki_open("/dummy", O_RDONLY, 0);
1122 EXPECT_NE(0, fd);
1124 char buf[20];
1125 EXPECT_EQ(-1, ki_read(fd, &buf[0], 20));
1126 // The Filesystem should be able to return whatever error it wants and have it
1127 // propagate through.
1128 EXPECT_EQ(1234, errno);