ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / native_client_sdk / src / tests / nacl_io_test / kernel_proxy_test.cc
blobc46065e1bc619fffdd2590fb8c9ac449be0ef5f9
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/osmman.h"
27 #include "nacl_io/ostime.h"
28 #include "nacl_io/path.h"
29 #include "nacl_io/typed_fs_factory.h"
31 using namespace nacl_io;
32 using namespace sdk_util;
34 using ::testing::_;
35 using ::testing::DoAll;
36 using ::testing::Invoke;
37 using ::testing::Return;
38 using ::testing::SaveArg;
39 using ::testing::SetArgPointee;
40 using ::testing::StrEq;
41 using ::testing::WithArgs;
43 namespace {
45 class KernelProxyTest_KernelProxy : public KernelProxy {
46 public:
47 Filesystem* RootFs() {
48 ScopedFilesystem fs;
49 Path path;
51 AcquireFsAndRelPath("/", &fs, &path);
52 return fs.get();
56 class KernelProxyTest : public ::testing::Test {
57 public:
58 KernelProxyTest() {}
60 void SetUp() {
61 ASSERT_EQ(0, ki_push_state_for_testing());
62 ASSERT_EQ(0, ki_init(&kp_));
63 // Unmount the passthrough FS and mount a memfs.
64 EXPECT_EQ(0, kp_.umount("/"));
65 EXPECT_EQ(0, kp_.mount("", "/", "memfs", 0, NULL));
68 void TearDown() { ki_uninit(); }
70 protected:
71 KernelProxyTest_KernelProxy kp_;
74 } // namespace
76 static int ki_fcntl_wrapper(int fd, int request, ...) {
77 va_list ap;
78 va_start(ap, request);
79 int rtn = ki_fcntl(fd, request, ap);
80 va_end(ap);
81 return rtn;
84 /**
85 * Test for fcntl commands F_SETFD and F_GETFD. This
86 * is tested here rather than in the mount_node tests
87 * since the fd flags are not stored in the kernel_handle
88 * or the filesystem node but directly in the FD mapping.
90 TEST_F(KernelProxyTest, Fcntl_GETFD) {
91 int fd = ki_open("/test", O_RDWR | O_CREAT, 0777);
92 ASSERT_NE(-1, fd);
94 // FD flags should start as zero.
95 ASSERT_EQ(0, ki_fcntl_wrapper(fd, F_GETFD));
97 // Check that setting FD_CLOEXEC works
98 int flags = FD_CLOEXEC;
99 ASSERT_EQ(0, ki_fcntl_wrapper(fd, F_SETFD, flags))
100 << "fcntl failed with: " << strerror(errno);
101 ASSERT_EQ(FD_CLOEXEC, ki_fcntl_wrapper(fd, F_GETFD));
103 // Check that setting invalid flag causes EINVAL
104 flags = FD_CLOEXEC + 1;
105 ASSERT_EQ(-1, ki_fcntl_wrapper(fd, F_SETFD, flags));
106 ASSERT_EQ(EINVAL, errno);
109 TEST_F(KernelProxyTest, FileLeak) {
110 const size_t buffer_size = 1024;
111 char filename[128];
112 int garbage[buffer_size];
114 MemFs* filesystem = (MemFs*)kp_.RootFs();
115 ScopedNode root;
117 ASSERT_EQ(0, filesystem->Open(Path("/"), O_RDONLY, &root));
118 ASSERT_EQ(0, root->ChildCount());
120 for (int file_num = 0; file_num < 4096; file_num++) {
121 sprintf(filename, "/foo%i.tmp", file_num++);
122 int fd = ki_open(filename, O_WRONLY | O_CREAT, 0777);
123 ASSERT_GT(fd, -1);
124 ASSERT_EQ(1, root->ChildCount());
125 ASSERT_EQ(buffer_size, ki_write(fd, garbage, buffer_size));
126 ki_close(fd);
127 ASSERT_EQ(0, ki_remove(filename));
129 ASSERT_EQ(0, root->ChildCount());
132 static bool g_handler_called = false;
133 static void sighandler(int) { g_handler_called = true; }
135 TEST_F(KernelProxyTest, Sigaction) {
136 struct sigaction action;
137 struct sigaction oaction;
138 memset(&action, 0, sizeof(action));
140 // Invalid signum
141 ASSERT_EQ(-1, ki_sigaction(-1, NULL, &oaction));
142 ASSERT_EQ(-1, ki_sigaction(SIGSTOP, NULL, &oaction));
143 ASSERT_EQ(EINVAL, errno);
145 // Get existing handler
146 memset(&oaction, 0, sizeof(oaction));
147 ASSERT_EQ(0, ki_sigaction(SIGINT, NULL, &oaction));
148 ASSERT_EQ(SIG_DFL, oaction.sa_handler);
150 // Attempt to set handler for unsupported signum
151 action.sa_handler = sighandler;
152 ASSERT_EQ(-1, ki_sigaction(SIGINT, &action, NULL));
153 ASSERT_EQ(EINVAL, errno);
155 // Attempt to set handler for supported signum
156 action.sa_handler = sighandler;
157 ASSERT_EQ(0, ki_sigaction(SIGWINCH, &action, NULL));
159 memset(&oaction, 0, sizeof(oaction));
160 ASSERT_EQ(0, ki_sigaction(SIGWINCH, NULL, &oaction));
161 ASSERT_EQ((sighandler_t*)sighandler, (sighandler_t*)oaction.sa_handler);
164 TEST_F(KernelProxyTest, KillSignals) {
165 // SIGSEGV can't be sent via kill(2)
166 ASSERT_EQ(-1, ki_kill(0, SIGSEGV)) << "kill(SEGV) failed to return an error";
167 ASSERT_EQ(EINVAL, errno) << "kill(SEGV) failed to set errno to EINVAL";
169 // Our implemenation should understand SIGWINCH
170 ASSERT_EQ(0, ki_kill(0, SIGWINCH)) << "kill(SIGWINCH) failed: " << errno;
172 // And USR1/USR2
173 ASSERT_EQ(0, ki_kill(0, SIGUSR1)) << "kill(SIGUSR1) failed: " << errno;
174 ASSERT_EQ(0, ki_kill(0, SIGUSR2)) << "kill(SIGUSR2) failed: " << errno;
177 TEST_F(KernelProxyTest, KillPIDValues) {
178 // Any PID other than 0, -1 and getpid() should yield ESRCH
179 // since there is only one valid process under NaCl
180 int mypid = getpid();
181 ASSERT_EQ(0, ki_kill(0, SIGWINCH));
182 ASSERT_EQ(0, ki_kill(-1, SIGWINCH));
183 ASSERT_EQ(0, ki_kill(mypid, SIGWINCH));
185 // Don't use mypid + 1 since getpid() actually returns -1
186 // when the IRT interface is missing (e.g. within chrome),
187 // and 0 is always a valid PID when calling kill().
188 int invalid_pid = mypid + 10;
189 ASSERT_EQ(-1, ki_kill(invalid_pid, SIGWINCH));
190 ASSERT_EQ(ESRCH, errno);
193 TEST_F(KernelProxyTest, SignalValues) {
194 ASSERT_EQ(ki_signal(SIGSEGV, sighandler), SIG_ERR)
195 << "registering SEGV handler didn't fail";
196 ASSERT_EQ(errno, EINVAL) << "signal(SEGV) failed to set errno to EINVAL";
198 ASSERT_EQ(ki_signal(-1, sighandler), SIG_ERR)
199 << "registering handler for invalid signal didn't fail";
200 ASSERT_EQ(errno, EINVAL) << "signal(-1) failed to set errno to EINVAL";
203 TEST_F(KernelProxyTest, SignalHandlerValues) {
204 // Unsupported signal.
205 ASSERT_NE(SIG_ERR, ki_signal(SIGSEGV, SIG_DFL));
206 ASSERT_EQ(SIG_ERR, ki_signal(SIGSEGV, SIG_IGN));
207 ASSERT_EQ(SIG_ERR, ki_signal(SIGSEGV, sighandler));
209 // Supported signal.
210 ASSERT_NE(SIG_ERR, ki_signal(SIGWINCH, SIG_DFL));
211 ASSERT_NE(SIG_ERR, ki_signal(SIGWINCH, SIG_IGN));
212 ASSERT_NE(SIG_ERR, ki_signal(SIGWINCH, sighandler));
215 TEST_F(KernelProxyTest, SignalSigwinch) {
216 g_handler_called = false;
218 // Register WINCH handler
219 sighandler_t newsig = sighandler;
220 sighandler_t oldsig = ki_signal(SIGWINCH, newsig);
221 ASSERT_NE(oldsig, SIG_ERR);
223 // Send signal.
224 ki_kill(0, SIGWINCH);
226 // Verify that handler was called
227 EXPECT_TRUE(g_handler_called);
229 // Restore existing handler
230 oldsig = ki_signal(SIGWINCH, oldsig);
232 // Verify the our newsig was returned as previous handler
233 ASSERT_EQ(oldsig, newsig);
236 TEST_F(KernelProxyTest, Rename) {
237 // Create a dummy file
238 int file1 = ki_open("/test1.txt", O_RDWR | O_CREAT, 0777);
239 ASSERT_GT(file1, -1);
240 ASSERT_EQ(0, ki_close(file1));
242 // Test the renaming works
243 ASSERT_EQ(0, ki_rename("/test1.txt", "/test2.txt"));
245 // Test that renaming across mount points fails
246 ASSERT_EQ(0, ki_mount("", "/foo", "memfs", 0, ""));
247 ASSERT_EQ(-1, ki_rename("/test2.txt", "/foo/test2.txt"));
248 ASSERT_EQ(EXDEV, errno);
251 TEST_F(KernelProxyTest, WorkingDirectory) {
252 char text[1024];
254 text[0] = 0;
255 ki_getcwd(text, sizeof(text));
256 EXPECT_STREQ("/", text);
258 char* alloc = ki_getwd(NULL);
259 EXPECT_EQ((char*)NULL, alloc);
260 EXPECT_EQ(EFAULT, errno);
262 text[0] = 0;
263 alloc = ki_getwd(text);
264 EXPECT_STREQ("/", alloc);
266 EXPECT_EQ(-1, ki_chdir("/foo"));
267 EXPECT_EQ(ENOENT, errno);
269 EXPECT_EQ(0, ki_chdir("/"));
271 EXPECT_EQ(0, ki_mkdir("/foo", S_IRUSR | S_IWUSR));
272 EXPECT_EQ(-1, ki_mkdir("/foo", S_IRUSR | S_IWUSR));
273 EXPECT_EQ(EEXIST, errno);
275 memset(text, 0, sizeof(text));
276 EXPECT_EQ(0, ki_chdir("foo"));
277 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
278 EXPECT_STREQ("/foo", text);
280 memset(text, 0, sizeof(text));
281 EXPECT_EQ(-1, ki_chdir("foo"));
282 EXPECT_EQ(ENOENT, errno);
283 EXPECT_EQ(0, ki_chdir(".."));
284 EXPECT_EQ(0, ki_chdir("/foo"));
285 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
286 EXPECT_STREQ("/foo", text);
289 TEST_F(KernelProxyTest, FDPathMapping) {
290 char text[1024];
292 int fd1, fd2, fd3, fd4, fd5;
294 EXPECT_EQ(0, ki_mkdir("/foo", S_IRUSR | S_IWUSR));
295 EXPECT_EQ(0, ki_mkdir("/foo/bar", S_IRUSR | S_IWUSR));
296 EXPECT_EQ(0, ki_mkdir("/example", S_IRUSR | S_IWUSR));
297 ki_chdir("/foo");
299 fd1 = ki_open("/example", O_RDONLY, 0);
300 EXPECT_NE(-1, fd1);
301 EXPECT_EQ(ki_fchdir(fd1), 0);
302 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
303 EXPECT_STREQ("/example", text);
305 EXPECT_EQ(0, ki_chdir("/foo"));
306 fd2 = ki_open("../example", O_RDONLY, 0);
307 EXPECT_NE(-1, fd2);
308 EXPECT_EQ(0, ki_fchdir(fd2));
309 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
310 EXPECT_STREQ("/example", text);
312 EXPECT_EQ(0, ki_chdir("/foo"));
313 fd3 = ki_open("../test", O_CREAT | O_RDWR, 0777);
314 EXPECT_NE(-1, fd3);
315 EXPECT_EQ(-1, ki_fchdir(fd3));
316 EXPECT_EQ(ENOTDIR, errno);
318 EXPECT_EQ(0, ki_chdir("/foo"));
319 fd4 = ki_open("bar", O_RDONLY, 0);
320 EXPECT_EQ(0, ki_fchdir(fd4));
321 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
322 EXPECT_STREQ("/foo/bar", text);
323 EXPECT_EQ(0, ki_chdir("/example"));
324 EXPECT_EQ(0, ki_fchdir(fd4));
325 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
326 EXPECT_STREQ("/foo/bar", text);
328 EXPECT_EQ(0, ki_chdir("/example"));
329 fd5 = ki_dup(fd4);
330 ASSERT_GT(fd5, -1);
331 ASSERT_NE(fd4, fd5);
332 EXPECT_EQ(0, ki_fchdir(fd5));
333 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
334 EXPECT_STREQ("/foo/bar", text);
336 fd5 = 123;
338 EXPECT_EQ(0, ki_chdir("/example"));
339 EXPECT_EQ(fd5, ki_dup2(fd4, fd5));
340 EXPECT_EQ(0, ki_fchdir(fd5));
341 EXPECT_EQ(text, ki_getcwd(text, sizeof(text)));
342 EXPECT_STREQ("/foo/bar", text);
345 TEST_F(KernelProxyTest, BasicReadWrite) {
346 char text[1024];
347 int fd1, fd2, fd3;
348 int len;
350 // Fail to delete non existant "/foo"
351 EXPECT_EQ(-1, ki_rmdir("/foo"));
352 EXPECT_EQ(ENOENT, errno);
354 // Create "/foo"
355 EXPECT_EQ(0, ki_mkdir("/foo", S_IRUSR | S_IWUSR));
356 EXPECT_EQ(-1, ki_mkdir("/foo", S_IRUSR | S_IWUSR));
357 EXPECT_EQ(EEXIST, errno);
359 // Delete "/foo"
360 EXPECT_EQ(0, ki_rmdir("/foo"));
362 // Recreate "/foo"
363 EXPECT_EQ(0, ki_mkdir("/foo", S_IRUSR | S_IWUSR));
365 // Fail to open "/foo/bar"
366 EXPECT_EQ(-1, ki_open("/foo/bar", O_RDONLY, 0));
367 EXPECT_EQ(ENOENT, errno);
369 // Create bar "/foo/bar"
370 fd1 = ki_open("/foo/bar", O_RDWR | O_CREAT, 0777);
371 ASSERT_NE(-1, fd1);
373 // Open (optionally create) bar "/foo/bar"
374 fd2 = ki_open("/foo/bar", O_RDWR | O_CREAT, 0777);
375 ASSERT_NE(-1, fd2);
377 // Fail to exclusively create bar "/foo/bar"
378 EXPECT_EQ(-1, ki_open("/foo/bar", O_RDONLY | O_CREAT | O_EXCL, 0777));
379 EXPECT_EQ(EEXIST, errno);
381 // Write hello and world to same node with different descriptors
382 // so that we overwrite each other
383 EXPECT_EQ(5, ki_write(fd2, "WORLD", 5));
384 EXPECT_EQ(5, ki_write(fd1, "HELLO", 5));
386 fd3 = ki_open("/foo/bar", O_RDONLY, 0);
387 ASSERT_NE(-1, fd3);
389 len = ki_read(fd3, text, sizeof(text));
390 ASSERT_EQ(5, len);
391 text[len] = 0;
392 EXPECT_STREQ("HELLO", text);
393 EXPECT_EQ(0, ki_close(fd1));
394 EXPECT_EQ(0, ki_close(fd2));
396 fd1 = ki_open("/foo/bar", O_WRONLY | O_APPEND, 0);
397 ASSERT_NE(-1, fd1);
398 EXPECT_EQ(5, ki_write(fd1, "WORLD", 5));
400 len = ki_read(fd3, text, sizeof(text));
401 ASSERT_EQ(5, len);
402 text[len] = 0;
403 EXPECT_STREQ("WORLD", text);
405 fd2 = ki_open("/foo/bar", O_RDONLY, 0);
406 ASSERT_NE(-1, fd2);
407 len = ki_read(fd2, text, sizeof(text));
408 if (len > 0)
409 text[len] = 0;
410 EXPECT_EQ(10, len);
411 EXPECT_STREQ("HELLOWORLD", text);
414 TEST_F(KernelProxyTest, FTruncate) {
415 char text[1024];
416 int fd1, fd2;
418 // Open a file write only, write some text, then test that using a
419 // separate file descriptor pointing to it that it is correctly
420 // truncated at a specified number of bytes (2).
421 fd1 = ki_open("/trunc", O_WRONLY | O_CREAT, 0777);
422 ASSERT_NE(-1, fd1);
423 fd2 = ki_open("/trunc", O_RDONLY, 0);
424 ASSERT_NE(-1, fd2);
425 EXPECT_EQ(5, ki_write(fd1, "HELLO", 5));
426 EXPECT_EQ(0, ki_ftruncate(fd1, 2));
427 // Verify the remaining file (using fd2, opened pre-truncation) is
428 // only 2 bytes in length.
429 EXPECT_EQ(2, ki_read(fd2, text, sizeof(text)));
430 EXPECT_EQ(0, ki_close(fd1));
431 EXPECT_EQ(0, ki_close(fd2));
433 // Truncate should fail if the file is not writable.
434 EXPECT_EQ(0, ki_chmod("/trunc", 0444));
435 fd2 = ki_open("/trunc", O_RDONLY, 0);
436 ASSERT_NE(-1, fd2);
437 EXPECT_EQ(-1, ki_ftruncate(fd2, 0));
438 EXPECT_EQ(EACCES, errno);
441 TEST_F(KernelProxyTest, Truncate) {
442 char text[1024];
443 int fd1;
445 // Open a file write only, write some text, then test that by
446 // referring to it by its path and truncating it we correctly truncate
447 // it at a specified number of bytes (2).
448 fd1 = ki_open("/trunc", O_WRONLY | O_CREAT, 0777);
449 ASSERT_NE(-1, fd1);
450 EXPECT_EQ(5, ki_write(fd1, "HELLO", 5));
451 EXPECT_EQ(0, ki_close(fd1));
452 EXPECT_EQ(0, ki_truncate("/trunc", 2));
453 // Verify the text is only 2 bytes long with new file descriptor.
454 fd1 = ki_open("/trunc", O_RDONLY, 0);
455 ASSERT_NE(-1, fd1);
456 EXPECT_EQ(2, ki_read(fd1, text, sizeof(text)));
457 EXPECT_EQ(0, ki_close(fd1));
459 // Truncate should fail if the file is not writable.
460 EXPECT_EQ(0, ki_chmod("/trunc", 0444));
461 EXPECT_EQ(-1, ki_truncate("/trunc", 0));
462 EXPECT_EQ(EACCES, errno);
465 TEST_F(KernelProxyTest, Lseek) {
466 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
467 ASSERT_GT(fd, -1);
468 ASSERT_EQ(9, ki_write(fd, "Some text", 9));
470 ASSERT_EQ(9, ki_lseek(fd, 0, SEEK_CUR));
471 ASSERT_EQ(9, ki_lseek(fd, 0, SEEK_END));
472 ASSERT_EQ(-1, ki_lseek(fd, -1, SEEK_SET));
473 ASSERT_EQ(EINVAL, errno);
475 // Seek past end of file.
476 ASSERT_EQ(13, ki_lseek(fd, 13, SEEK_SET));
477 char buffer[4];
478 memset(&buffer[0], 0xfe, 4);
479 ASSERT_EQ(9, ki_lseek(fd, -4, SEEK_END));
480 ASSERT_EQ(9, ki_lseek(fd, 0, SEEK_CUR));
481 ASSERT_EQ(4, ki_read(fd, &buffer[0], 4));
482 ASSERT_EQ(0, memcmp("\0\0\0\0", buffer, 4));
485 TEST_F(KernelProxyTest, CloseTwice) {
486 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
487 ASSERT_GT(fd, -1);
489 EXPECT_EQ(9, ki_write(fd, "Some text", 9));
491 int fd2 = ki_dup(fd);
492 ASSERT_GT(fd2, -1);
494 EXPECT_EQ(0, ki_close(fd));
495 EXPECT_EQ(0, ki_close(fd2));
498 TEST_F(KernelProxyTest, Dup) {
499 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
500 ASSERT_GT(fd, -1);
502 int dup_fd = ki_dup(fd);
503 ASSERT_NE(-1, dup_fd);
505 ASSERT_EQ(9, ki_write(fd, "Some text", 9));
506 ASSERT_EQ(9, ki_lseek(fd, 0, SEEK_CUR));
507 ASSERT_EQ(9, ki_lseek(dup_fd, 0, SEEK_CUR));
509 int dup2_fd = 123;
510 ASSERT_EQ(dup2_fd, ki_dup2(fd, dup2_fd));
511 ASSERT_EQ(9, ki_lseek(dup2_fd, 0, SEEK_CUR));
513 int new_fd = ki_open("/bar", O_CREAT | O_RDWR, 0777);
515 ASSERT_EQ(fd, ki_dup2(new_fd, fd));
516 // fd, new_fd -> "/bar"
517 // dup_fd, dup2_fd -> "/foo"
519 // We should still be able to write to dup_fd (i.e. it should not be closed).
520 ASSERT_EQ(4, ki_write(dup_fd, "more", 4));
522 ASSERT_EQ(0, ki_close(dup2_fd));
523 // fd, new_fd -> "/bar"
524 // dup_fd -> "/foo"
526 ASSERT_EQ(dup_fd, ki_dup2(fd, dup_fd));
527 // fd, new_fd, dup_fd -> "/bar"
530 TEST_F(KernelProxyTest, DescriptorDup2Dance) {
531 // Open a file to a get a descriptor to copy for this test.
532 // The test makes the assumption at all descriptors
533 // open by default are contiguous starting from zero.
534 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
535 ASSERT_GT(fd, -1);
537 // The comment above each statement below tracks which descriptors,
538 // starting from fd are currently allocated.
539 // Descriptors marked with an 'x' are allocated.
541 // (fd) (fd + 1) (fd + 2)
542 // x
543 ASSERT_EQ(fd + 1, ki_dup2(fd, fd + 1));
544 // (fd) (fd + 1) (fd + 2)
545 // x x
546 ASSERT_EQ(0, ki_close(fd + 1));
547 // (fd) (fd + 1) (fd + 2)
548 // x
549 ASSERT_EQ(fd + 1, ki_dup2(fd, fd + 1));
550 // (fd) (fd + 1) (fd + 2)
551 // x x
552 ASSERT_EQ(fd + 2, ki_dup(fd));
553 // (fd) (fd + 1) (fd + 2)
554 // x x x
555 ASSERT_EQ(0, ki_close(fd + 2));
556 // (fd) (fd + 1) (fd + 2)
557 // x x
558 ASSERT_EQ(0, ki_close(fd + 1));
559 // (fd) (fd + 1) (fd + 2)
560 // x
561 ASSERT_EQ(0, ki_close(fd));
564 TEST_F(KernelProxyTest, Dup2Negative) {
565 // Open a file to a get a descriptor to copy for this test.
566 // The test makes the assumption at all descriptors
567 // open by default are contiguous starting from zero.
568 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
569 ASSERT_GT(fd, -1);
571 // Attempt to dup2 to an invalid descriptor.
572 ASSERT_EQ(-1, ki_dup2(fd, -12));
573 EXPECT_EQ(EBADF, errno);
574 ASSERT_EQ(0, ki_close(fd));
577 TEST_F(KernelProxyTest, DescriptorAllocationConsistency) {
578 // Check that the descriptor free list returns the expected ones,
579 // as the order is mandated by POSIX.
581 // Open a file to a get a descriptor to copy for this test.
582 // The test makes the assumption at all descriptors
583 // open by default are contiguous starting from zero.
584 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
585 ASSERT_GT(fd, -1);
587 // The next descriptor allocated should follow the first.
588 int dup_fd = ki_dup(fd);
589 ASSERT_EQ(fd + 1, dup_fd);
591 // Allocate a high descriptor number.
592 ASSERT_EQ(100, ki_dup2(fd, 100));
594 // The next descriptor allocate should still come 2 places
595 // after the first.
596 int dup_fd2 = ki_dup(fd);
597 ASSERT_EQ(fd + 2, dup_fd2);
600 TEST_F(KernelProxyTest, Lstat) {
601 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777);
602 ASSERT_GT(fd, -1);
603 ASSERT_EQ(0, ki_mkdir("/bar", S_IRUSR | S_IWUSR));
605 struct stat buf;
606 EXPECT_EQ(0, ki_lstat("/foo", &buf));
607 EXPECT_EQ(0, buf.st_size);
608 EXPECT_TRUE(S_ISREG(buf.st_mode));
610 EXPECT_EQ(0, ki_lstat("/bar", &buf));
611 EXPECT_EQ(0, buf.st_size);
612 EXPECT_TRUE(S_ISDIR(buf.st_mode));
614 EXPECT_EQ(-1, ki_lstat("/no-such-file", &buf));
615 EXPECT_EQ(ENOENT, errno);
617 // Still legal to stat a file that is write-only.
618 EXPECT_EQ(0, ki_chmod("/foo", 0222));
619 EXPECT_EQ(0, ki_lstat("/foo", &buf));
622 TEST_F(KernelProxyTest, Chmod) {
623 ASSERT_EQ(-1, ki_chmod("/foo", 0222));
624 ASSERT_EQ(errno, ENOENT);
626 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0770);
627 ASSERT_GT(fd, -1);
629 struct stat buf;
630 ASSERT_EQ(0, ki_stat("/foo", &buf));
631 ASSERT_EQ(0770, buf.st_mode & 0777);
633 ASSERT_EQ(0, ki_chmod("/foo", 0222));
634 ASSERT_EQ(0, ki_stat("/foo", &buf));
635 ASSERT_EQ(0222, buf.st_mode & 0777);
637 // Check that passing mode bits other than permissions
638 // is ignored.
639 ASSERT_EQ(0, ki_chmod("/foo", S_IFBLK | 0222));
640 ASSERT_EQ(0, ki_stat("/foo", &buf));
641 EXPECT_TRUE(S_ISREG(buf.st_mode));
642 ASSERT_EQ(0222, buf.st_mode & 0777);
645 TEST_F(KernelProxyTest, Fchmod) {
646 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0770);
647 ASSERT_GT(fd, -1);
649 struct stat buf;
650 ASSERT_EQ(0, ki_stat("/foo", &buf));
651 ASSERT_EQ(0770, buf.st_mode & 0777);
653 ASSERT_EQ(0, ki_fchmod(fd, 0222));
654 ASSERT_EQ(0, ki_stat("/foo", &buf));
655 ASSERT_EQ(0222, buf.st_mode & 0777);
657 // Check that passing mode bits other than permissions
658 // is ignored.
659 ASSERT_EQ(0, ki_fchmod(fd, S_IFBLK | 0222));
660 ASSERT_EQ(0, ki_stat("/foo", &buf));
661 EXPECT_TRUE(S_ISREG(buf.st_mode));
662 ASSERT_EQ(0222, buf.st_mode & 0777);
665 TEST_F(KernelProxyTest, OpenDirectory) {
666 // Opening a directory for read should succeed.
667 int fd = ki_open("/", O_RDONLY, 0);
668 ASSERT_GT(fd, -1);
670 // Opening a directory for write should fail.
671 EXPECT_EQ(-1, ki_open("/", O_RDWR, 0));
672 EXPECT_EQ(errno, EISDIR);
673 EXPECT_EQ(-1, ki_open("/", O_WRONLY, 0));
674 EXPECT_EQ(errno, EISDIR);
677 TEST_F(KernelProxyTest, OpenWithMode) {
678 int fd = ki_open("/foo", O_CREAT | O_RDWR, 0723);
679 ASSERT_GT(fd, -1);
681 struct stat buf;
682 EXPECT_EQ(0, ki_lstat("/foo", &buf));
683 EXPECT_EQ(0723, buf.st_mode & 0777);
686 TEST_F(KernelProxyTest, CreateWronlyWithReadOnlyMode) {
687 int fd = ki_open("/foo", O_CREAT | O_WRONLY, 0444);
688 ASSERT_GT(fd, -1);
691 TEST_F(KernelProxyTest, UseAfterClose) {
692 int fd = ki_open("/dummy", O_CREAT | O_WRONLY, 0777);
693 ASSERT_GT(fd, -1);
694 EXPECT_EQ(5, ki_write(fd, "hello", 5));
695 EXPECT_EQ(0, ki_close(fd));
696 EXPECT_EQ(-1, ki_write(fd, "hello", 5));
697 EXPECT_EQ(EBADF, errno);
700 TEST_F(KernelProxyTest, Utimes) {
701 struct timeval times[2];
702 times[0].tv_sec = 1000;
703 times[0].tv_usec = 2000;
704 times[1].tv_sec = 3000;
705 times[1].tv_usec = 4000;
707 int fd = ki_open("/dummy", O_CREAT | O_WRONLY, 0222);
708 ASSERT_GT(fd, -1);
709 EXPECT_EQ(0, ki_close(fd));
711 // utime should work if the file is write-only.
712 EXPECT_EQ(0, ki_utimes("/dummy", times));
714 // utime should work on directories (which can never be opened for write)
715 EXPECT_EQ(0, ki_utimes("/", times));
717 // or if the file is read-only.
718 EXPECT_EQ(0, ki_chmod("/dummy", 0444));
719 EXPECT_EQ(0, ki_utimes("/dummy", times));
721 // times can be NULL. In that case the access/mod times will be set to the
722 // current time.
723 struct timeval tm;
724 EXPECT_EQ(0, gettimeofday(&tm, NULL));
726 EXPECT_EQ(0, ki_utimes("/dummy", NULL));
727 struct stat buf;
728 EXPECT_EQ(0, ki_stat("/dummy", &buf));
730 // We just want to check if st_atime >= tm. This is true if atime seconds > tm
731 // seconds (in which case the nanoseconds are irrelevant), or if the seconds
732 // are equal, then this is true if atime nanoseconds >= tm microseconds.
733 EXPECT_TRUE(
734 buf.st_atime > tm.tv_sec ||
735 (buf.st_atime == tm.tv_sec && buf.st_atimensec >= tm.tv_usec * 1000));
736 EXPECT_TRUE(
737 buf.st_mtime > tm.tv_sec ||
738 (buf.st_mtime == tm.tv_sec && buf.st_mtimensec >= tm.tv_usec * 1000));
741 TEST_F(KernelProxyTest, Utime) {
742 struct utimbuf times;
743 times.actime = 1000;
744 times.modtime = 2000;
746 int fd = ki_open("/dummy", O_CREAT | O_WRONLY, 0222);
747 ASSERT_GT(fd, -1);
748 EXPECT_EQ(0, ki_close(fd));
750 // utime should work if the file is write-only.
751 EXPECT_EQ(0, ki_utime("/dummy", &times));
753 // or if the file is read-only.
754 EXPECT_EQ(0, ki_chmod("/dummy", 0444));
755 EXPECT_EQ(0, ki_utime("/dummy", &times));
757 // times can be NULL. In that case the access/mod times will be set to the
758 // current time.
759 struct timeval tm;
760 EXPECT_EQ(0, gettimeofday(&tm, NULL));
762 EXPECT_EQ(0, ki_utime("/dummy", NULL));
763 struct stat buf;
764 EXPECT_EQ(0, ki_stat("/dummy", &buf));
766 // We just want to check if st_atime >= tm. This is true if atime seconds > tm
767 // seconds (in which case the nanoseconds are irrelevant), or if the seconds
768 // are equal, then this is true if atime nanoseconds >= tm microseconds.
769 EXPECT_TRUE(
770 buf.st_atime > tm.tv_sec ||
771 (buf.st_atime == tm.tv_sec && buf.st_atimensec >= tm.tv_usec * 1000));
772 EXPECT_TRUE(
773 buf.st_mtime > tm.tv_sec ||
774 (buf.st_mtime == tm.tv_sec && buf.st_mtimensec >= tm.tv_usec * 1000));
777 TEST_F(KernelProxyTest, Umask) {
778 mode_t oldmask = ki_umask(0222);
779 EXPECT_EQ(0, oldmask);
781 int fd = ki_open("/foo", O_CREAT | O_RDONLY, 0666);
782 ASSERT_GT(fd, -1);
783 ki_close(fd);
785 EXPECT_EQ(0, ki_mkdir("/dir", 0777));
787 struct stat buf;
788 EXPECT_EQ(0, ki_stat("/foo", &buf));
789 EXPECT_EQ(0444, buf.st_mode & 0777);
791 EXPECT_EQ(0, ki_stat("/dir", &buf));
792 EXPECT_EQ(0555, buf.st_mode & 0777);
794 EXPECT_EQ(0222, ki_umask(0));
797 namespace {
799 StringMap_t g_string_map;
800 bool g_fs_ioctl_called;
801 int g_fs_dev;
803 class KernelProxyMountTest_Filesystem : public MemFs {
804 public:
805 virtual Error Init(const FsInitArgs& args) {
806 MemFs::Init(args);
808 g_string_map = args.string_map;
809 g_fs_dev = args.dev;
811 if (g_string_map.find("false") != g_string_map.end())
812 return EINVAL;
813 return 0;
816 virtual Error Filesystem_VIoctl(int request, va_list arglist) {
817 g_fs_ioctl_called = true;
818 return 0;
821 friend class TypedFsFactory<KernelProxyMountTest_Filesystem>;
824 class KernelProxyMountTest_KernelProxy : public KernelProxy {
825 virtual Error Init(PepperInterface* ppapi) {
826 KernelProxy::Init(NULL);
827 factories_["initfs"] = new TypedFsFactory<KernelProxyMountTest_Filesystem>;
828 return 0;
832 class KernelProxyMountTest : public ::testing::Test {
833 public:
834 KernelProxyMountTest() {}
836 void SetUp() {
837 g_string_map.clear();
838 g_fs_dev = -1;
839 g_fs_ioctl_called = false;
841 ASSERT_EQ(0, ki_push_state_for_testing());
842 ASSERT_EQ(0, ki_init(&kp_));
845 void TearDown() {
846 g_string_map.clear();
847 ki_uninit();
850 protected:
851 KernelProxyMountTest_KernelProxy kp_;
854 // Helper function for calling ki_ioctl without having
855 // to construct a va_list.
856 int ki_ioctl_wrapper(int fd, int request, ...) {
857 va_list ap;
858 va_start(ap, request);
859 int rtn = ki_ioctl(fd, request, ap);
860 va_end(ap);
861 return rtn;
864 } // namespace
866 TEST_F(KernelProxyMountTest, MountInit) {
867 int res1 = ki_mount("/", "/mnt1", "initfs", 0, "false,foo=bar");
869 EXPECT_EQ("bar", g_string_map["foo"]);
870 EXPECT_EQ(-1, res1);
871 EXPECT_EQ(EINVAL, errno);
873 int res2 = ki_mount("/", "/mnt2", "initfs", 0, "true,bar=foo,x=y");
874 EXPECT_NE(-1, res2);
875 EXPECT_EQ("y", g_string_map["x"]);
878 TEST_F(KernelProxyMountTest, MountAndIoctl) {
879 ASSERT_EQ(0, ki_mount("/", "/mnt1", "initfs", 0, ""));
880 ASSERT_NE(-1, g_fs_dev);
882 char path[100];
883 snprintf(path, 100, "dev/fs/%d", g_fs_dev);
885 int fd = ki_open(path, O_RDONLY, 0);
886 ASSERT_GT(fd, -1);
888 EXPECT_EQ(0, ki_ioctl_wrapper(fd, 0xdeadbeef));
889 EXPECT_EQ(true, g_fs_ioctl_called);
892 static void mount_callback(const char* source,
893 const char* target,
894 const char* filesystemtype,
895 unsigned long mountflags,
896 const void* data,
897 dev_t dev,
898 void* user_data) {
899 EXPECT_STREQ("/", source);
900 EXPECT_STREQ("/mnt1", target);
901 EXPECT_STREQ("initfs", filesystemtype);
902 EXPECT_EQ(0, mountflags);
903 EXPECT_STREQ("", (const char*) data);
904 EXPECT_EQ(g_fs_dev, dev);
906 bool* callback_called = static_cast<bool*>(user_data);
907 *callback_called = true;
910 TEST_F(KernelProxyMountTest, MountCallback) {
911 bool callback_called = false;
912 kp_.SetMountCallback(&mount_callback, &callback_called);
913 ASSERT_EQ(0, ki_mount("/", "/mnt1", "initfs", 0, ""));
914 ASSERT_NE(-1, g_fs_dev);
915 EXPECT_EQ(true, callback_called);
918 namespace {
920 int g_MMapCount = 0;
922 class KernelProxyMMapTest_Node : public Node {
923 public:
924 KernelProxyMMapTest_Node(Filesystem* filesystem)
925 : Node(filesystem), node_mmap_count_(0) {
926 EXPECT_EQ(0, Init(0));
929 virtual Error MMap(void* addr,
930 size_t length,
931 int prot,
932 int flags,
933 size_t offset,
934 void** out_addr) {
935 node_mmap_count_++;
936 switch (g_MMapCount++) {
937 case 0:
938 *out_addr = reinterpret_cast<void*>(0x1000);
939 break;
940 case 1:
941 *out_addr = reinterpret_cast<void*>(0x2000);
942 break;
943 case 2:
944 *out_addr = reinterpret_cast<void*>(0x3000);
945 break;
946 default:
947 return EPERM;
950 return 0;
953 private:
954 int node_mmap_count_;
957 class KernelProxyMMapTest_Filesystem : public Filesystem {
958 public:
959 virtual Error OpenWithMode(const Path& path, int open_flags,
960 mode_t mode, ScopedNode* out_node) {
961 out_node->reset(new KernelProxyMMapTest_Node(this));
962 return 0;
965 virtual Error OpenResource(const Path& path, ScopedNode* out_node) {
966 out_node->reset(NULL);
967 return ENOSYS;
969 virtual Error Unlink(const Path& path) { return ENOSYS; }
970 virtual Error Mkdir(const Path& path, int permissions) { return ENOSYS; }
971 virtual Error Rmdir(const Path& path) { return ENOSYS; }
972 virtual Error Remove(const Path& path) { return ENOSYS; }
973 virtual Error Rename(const Path& path, const Path& newpath) { return ENOSYS; }
975 friend class TypedFsFactory<KernelProxyMMapTest_Filesystem>;
978 class KernelProxyMMapTest_KernelProxy : public KernelProxy {
979 virtual Error Init(PepperInterface* ppapi) {
980 KernelProxy::Init(NULL);
981 factories_["mmapfs"] = new TypedFsFactory<KernelProxyMMapTest_Filesystem>;
982 return 0;
986 class KernelProxyMMapTest : public ::testing::Test {
987 public:
988 KernelProxyMMapTest() {}
990 void SetUp() {
991 ASSERT_EQ(0, ki_push_state_for_testing());
992 ASSERT_EQ(0, ki_init(&kp_));
995 void TearDown() { ki_uninit(); }
997 private:
998 KernelProxyMMapTest_KernelProxy kp_;
1001 } // namespace
1003 TEST_F(KernelProxyMMapTest, MMap) {
1004 ASSERT_EQ(0, ki_umount("/"));
1005 ASSERT_EQ(0, ki_mount("", "/", "mmapfs", 0, NULL));
1006 int fd = ki_open("/file", O_RDWR | O_CREAT, 0777);
1007 ASSERT_NE(-1, fd);
1009 void* addr1 = ki_mmap(NULL, 0x800, PROT_READ, MAP_PRIVATE, fd, 0);
1010 ASSERT_EQ(reinterpret_cast<void*>(0x1000), addr1);
1011 ASSERT_EQ(1, g_MMapCount);
1013 void* addr2 = ki_mmap(NULL, 0x800, PROT_READ, MAP_PRIVATE, fd, 0);
1014 ASSERT_EQ(reinterpret_cast<void*>(0x2000), addr2);
1015 ASSERT_EQ(2, g_MMapCount);
1017 void* addr3 = ki_mmap(NULL, 0x800, PROT_READ, MAP_PRIVATE, fd, 0);
1018 ASSERT_EQ(reinterpret_cast<void*>(0x3000), addr3);
1019 ASSERT_EQ(3, g_MMapCount);
1021 ki_close(fd);
1023 // We no longer track mmap'd regions, so munmap is a no-op.
1024 ASSERT_EQ(0, ki_munmap(reinterpret_cast<void*>(0x1000), 0x2800));
1025 // We don't track regions, so the mmap count hasn't changed.
1026 ASSERT_EQ(3, g_MMapCount);
1029 namespace {
1031 class SingletonFsFactory : public FsFactory {
1032 public:
1033 SingletonFsFactory(const ScopedFilesystem& filesystem) : mount_(filesystem) {}
1035 virtual Error CreateFilesystem(const FsInitArgs& args,
1036 ScopedFilesystem* out_fs) {
1037 *out_fs = mount_;
1038 return 0;
1041 private:
1042 ScopedFilesystem mount_;
1045 class KernelProxyErrorTest_KernelProxy : public KernelProxy {
1046 public:
1047 KernelProxyErrorTest_KernelProxy() : fs_(new MockFs) {}
1049 virtual Error Init(PepperInterface* ppapi) {
1050 KernelProxy::Init(ppapi);
1051 factories_["testfs"] = new SingletonFsFactory(fs_);
1053 EXPECT_CALL(*fs_, Destroy()).Times(1);
1054 return 0;
1057 ScopedRef<MockFs> fs() { return fs_; }
1059 private:
1060 ScopedRef<MockFs> fs_;
1063 class KernelProxyErrorTest : public ::testing::Test {
1064 public:
1065 KernelProxyErrorTest() {}
1067 void SetUp() {
1068 ASSERT_EQ(0, ki_push_state_for_testing());
1069 ASSERT_EQ(0, ki_init(&kp_));
1070 // Unmount the passthrough FS and mount a testfs.
1071 EXPECT_EQ(0, kp_.umount("/"));
1072 EXPECT_EQ(0, kp_.mount("", "/", "testfs", 0, NULL));
1075 void TearDown() { ki_uninit(); }
1077 ScopedRef<MockFs> fs() { return kp_.fs(); }
1079 private:
1080 KernelProxyErrorTest_KernelProxy kp_;
1083 } // namespace
1085 TEST_F(KernelProxyErrorTest, WriteError) {
1086 ScopedRef<MockFs> mock_fs(fs());
1087 ScopedRef<MockNode> mock_node(new MockNode(&*mock_fs));
1088 EXPECT_CALL(*mock_fs, OpenWithMode(_, _, _, _))
1089 .WillOnce(DoAll(SetArgPointee<3>(mock_node), Return(0)));
1091 EXPECT_CALL(*mock_node, Write(_, _, _, _))
1092 .WillOnce(DoAll(SetArgPointee<3>(0), // Wrote 0 bytes.
1093 Return(1234))); // Returned error 1234.
1095 EXPECT_CALL(*mock_node, IsaDir()).Times(1);
1096 EXPECT_CALL(*mock_node, Destroy()).Times(1);
1098 int fd = ki_open("/dummy", O_WRONLY, 0);
1099 EXPECT_NE(0, fd);
1101 char buf[20];
1102 EXPECT_EQ(-1, ki_write(fd, &buf[0], 20));
1103 // The Filesystem should be able to return whatever error it wants and have it
1104 // propagate through.
1105 EXPECT_EQ(1234, errno);
1108 TEST_F(KernelProxyErrorTest, ReadError) {
1109 ScopedRef<MockFs> mock_fs(fs());
1110 ScopedRef<MockNode> mock_node(new MockNode(&*mock_fs));
1111 EXPECT_CALL(*mock_fs, OpenWithMode(_, _, _, _))
1112 .WillOnce(DoAll(SetArgPointee<3>(mock_node), Return(0)));
1114 EXPECT_CALL(*mock_node, Read(_, _, _, _))
1115 .WillOnce(DoAll(SetArgPointee<3>(0), // Read 0 bytes.
1116 Return(1234))); // Returned error 1234.
1118 EXPECT_CALL(*mock_node, Destroy()).Times(1);
1120 int fd = ki_open("/dummy", O_RDONLY, 0);
1121 EXPECT_NE(0, fd);
1123 char buf[20];
1124 EXPECT_EQ(-1, ki_read(fd, &buf[0], 20));
1125 // The Filesystem should be able to return whatever error it wants and have it
1126 // propagate through.
1127 EXPECT_EQ(1234, errno);