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.
10 #include <sys/types.h>
16 #include "gmock/gmock.h"
17 #include "gtest/gtest.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
;
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
;
46 class KernelProxyTest_KernelProxy
: public KernelProxy
{
48 Filesystem
* RootFs() {
52 AcquireFsAndRelPath("/", &fs
, &path
);
57 class KernelProxyTest
: public ::testing::Test
{
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(); }
72 KernelProxyTest_KernelProxy kp_
;
77 static int ki_fcntl_wrapper(int fd
, int request
, ...) {
79 va_start(ap
, request
);
80 int rtn
= ki_fcntl(fd
, request
, ap
);
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);
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;
113 int garbage
[buffer_size
];
115 MemFs
* filesystem
= (MemFs
*)kp_
.RootFs();
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);
125 ASSERT_EQ(1, root
->ChildCount());
126 ASSERT_EQ(buffer_size
, ki_write(fd
, garbage
, buffer_size
));
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
));
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
;
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
));
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
);
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
) {
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
);
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
) {
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
));
300 fd1
= ki_open("/example", O_RDONLY
, 0);
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);
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);
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"));
333 EXPECT_EQ(0, ki_fchdir(fd5
));
334 EXPECT_EQ(text
, ki_getcwd(text
, sizeof(text
)));
335 EXPECT_STREQ("/foo/bar", text
);
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
) {
351 // Fail to delete non existant "/foo"
352 EXPECT_EQ(-1, ki_rmdir("/foo"));
353 EXPECT_EQ(ENOENT
, errno
);
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
);
361 EXPECT_EQ(0, ki_rmdir("/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);
374 // Open (optionally create) bar "/foo/bar"
375 fd2
= ki_open("/foo/bar", O_RDWR
| O_CREAT
, 0777);
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);
390 len
= ki_read(fd3
, text
, sizeof(text
));
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);
399 EXPECT_EQ(5, ki_write(fd1
, "WORLD", 5));
401 len
= ki_read(fd3
, text
, sizeof(text
));
404 EXPECT_STREQ("WORLD", text
);
406 fd2
= ki_open("/foo/bar", O_RDONLY
, 0);
408 len
= ki_read(fd2
, text
, sizeof(text
));
412 EXPECT_STREQ("HELLOWORLD", text
);
415 TEST_F(KernelProxyTest
, FTruncate
) {
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);
424 fd2
= ki_open("/trunc", O_RDONLY
, 0);
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);
438 EXPECT_EQ(-1, ki_ftruncate(fd2
, 0));
439 EXPECT_EQ(EACCES
, errno
);
442 TEST_F(KernelProxyTest
, Truncate
) {
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);
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);
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);
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
));
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);
490 EXPECT_EQ(9, ki_write(fd
, "Some text", 9));
492 int fd2
= ki_dup(fd
);
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);
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
));
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"
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);
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)
544 ASSERT_EQ(fd
+ 1, ki_dup2(fd
, fd
+ 1));
545 // (fd) (fd + 1) (fd + 2)
547 ASSERT_EQ(0, ki_close(fd
+ 1));
548 // (fd) (fd + 1) (fd + 2)
550 ASSERT_EQ(fd
+ 1, ki_dup2(fd
, fd
+ 1));
551 // (fd) (fd + 1) (fd + 2)
553 ASSERT_EQ(fd
+ 2, ki_dup(fd
));
554 // (fd) (fd + 1) (fd + 2)
556 ASSERT_EQ(0, ki_close(fd
+ 2));
557 // (fd) (fd + 1) (fd + 2)
559 ASSERT_EQ(0, ki_close(fd
+ 1));
560 // (fd) (fd + 1) (fd + 2)
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);
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);
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
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);
604 ASSERT_EQ(0, ki_mkdir("/bar", S_IRUSR
| S_IWUSR
));
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);
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
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);
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
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);
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);
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);
692 TEST_F(KernelProxyTest
, UseAfterClose
) {
693 int fd
= ki_open("/dummy", O_CREAT
| O_WRONLY
, 0777);
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);
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
725 EXPECT_EQ(0, gettimeofday(&tm
, NULL
));
727 EXPECT_EQ(0, ki_utimes("/dummy", NULL
));
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.
735 buf
.st_atime
> tm
.tv_sec
||
736 (buf
.st_atime
== tm
.tv_sec
&& buf
.st_atimensec
>= tm
.tv_usec
* 1000));
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
;
745 times
.modtime
= 2000;
747 int fd
= ki_open("/dummy", O_CREAT
| O_WRONLY
, 0222);
749 EXPECT_EQ(0, ki_close(fd
));
751 // utime should work if the file is write-only.
752 EXPECT_EQ(0, ki_utime("/dummy", ×
));
754 // or if the file is read-only.
755 EXPECT_EQ(0, ki_chmod("/dummy", 0444));
756 EXPECT_EQ(0, ki_utime("/dummy", ×
));
758 // times can be NULL. In that case the access/mod times will be set to the
761 EXPECT_EQ(0, gettimeofday(&tm
, NULL
));
763 EXPECT_EQ(0, ki_utime("/dummy", NULL
));
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.
771 buf
.st_atime
> tm
.tv_sec
||
772 (buf
.st_atime
== tm
.tv_sec
&& buf
.st_atimensec
>= tm
.tv_usec
* 1000));
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);
786 EXPECT_EQ(0, ki_mkdir("/dir", 0777));
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));
800 StringMap_t g_string_map
;
801 bool g_fs_ioctl_called
;
804 class KernelProxyMountTest_Filesystem
: public MemFs
{
806 virtual Error
Init(const FsInitArgs
& args
) {
809 g_string_map
= args
.string_map
;
812 if (g_string_map
.find("false") != g_string_map
.end())
817 virtual Error
Filesystem_VIoctl(int request
, va_list arglist
) {
818 g_fs_ioctl_called
= true;
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
>;
833 class KernelProxyMountTest
: public ::testing::Test
{
835 KernelProxyMountTest() {}
838 g_string_map
.clear();
840 g_fs_ioctl_called
= false;
842 ASSERT_EQ(0, ki_push_state_for_testing());
843 ASSERT_EQ(0, ki_init(&kp_
));
847 g_string_map
.clear();
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
, ...) {
859 va_start(ap
, request
);
860 int rtn
= ki_ioctl(fd
, request
, ap
);
867 TEST_F(KernelProxyMountTest
, MountInit
) {
868 int res1
= ki_mount("/", "/mnt1", "initfs", 0, "false,foo=bar");
870 EXPECT_EQ("bar", g_string_map
["foo"]);
872 EXPECT_EQ(EINVAL
, errno
);
874 int res2
= ki_mount("/", "/mnt2", "initfs", 0, "true,bar=foo,x=y");
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
);
884 snprintf(path
, 100, "dev/fs/%d", g_fs_dev
);
886 int fd
= ki_open(path
, O_RDONLY
, 0);
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
,
895 const char* filesystemtype
,
896 unsigned long mountflags
,
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
);
923 class KernelProxyMMapTest_Node
: public Node
{
925 KernelProxyMMapTest_Node(Filesystem
* filesystem
)
926 : Node(filesystem
), node_mmap_count_(0) {
927 EXPECT_EQ(0, Init(0));
930 virtual Error
MMap(void* addr
,
937 switch (g_MMapCount
++) {
939 *out_addr
= reinterpret_cast<void*>(0x1000);
942 *out_addr
= reinterpret_cast<void*>(0x2000);
945 *out_addr
= reinterpret_cast<void*>(0x3000);
955 int node_mmap_count_
;
958 class KernelProxyMMapTest_Filesystem
: public Filesystem
{
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));
966 virtual Error
OpenResource(const Path
& path
, ScopedNode
* out_node
) {
967 out_node
->reset(NULL
);
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
>;
987 class KernelProxyMMapTest
: public ::testing::Test
{
989 KernelProxyMMapTest() {}
992 ASSERT_EQ(0, ki_push_state_for_testing());
993 ASSERT_EQ(0, ki_init(&kp_
));
996 void TearDown() { ki_uninit(); }
999 KernelProxyMMapTest_KernelProxy kp_
;
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);
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
);
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
);
1032 class SingletonFsFactory
: public FsFactory
{
1034 SingletonFsFactory(const ScopedFilesystem
& filesystem
) : mount_(filesystem
) {}
1036 virtual Error
CreateFilesystem(const FsInitArgs
& args
,
1037 ScopedFilesystem
* out_fs
) {
1043 ScopedFilesystem mount_
;
1046 class KernelProxyErrorTest_KernelProxy
: public KernelProxy
{
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);
1058 ScopedRef
<MockFs
> fs() { return fs_
; }
1061 ScopedRef
<MockFs
> fs_
;
1064 class KernelProxyErrorTest
: public ::testing::Test
{
1066 KernelProxyErrorTest() {}
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(); }
1081 KernelProxyErrorTest_KernelProxy kp_
;
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);
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);
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
);