Index: native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc |
diff --git a/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc b/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc |
index 9069e0fbd68f0d9899f43dbb99ce809f12b6678e..3626a2f7a70edbd9a785a05b545ad7516af0bfd2 100644 |
--- a/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc |
+++ b/native_client_sdk/src/tests/nacl_io_test/kernel_proxy_test.cc |
@@ -74,6 +74,8 @@ class KernelProxyTest : public ::testing::Test { |
} // namespace |
+// Helper function for calling ki_fcntl without having |
+// to construct a va_list. |
static int ki_fcntl_wrapper(int fd, int request, ...) { |
va_list ap; |
va_start(ap, request); |
@@ -82,12 +84,69 @@ static int ki_fcntl_wrapper(int fd, int request, ...) { |
return rtn; |
} |
-/** |
- * Test for fcntl commands F_SETFD and F_GETFD. This |
- * is tested here rather than in the mount_node tests |
- * since the fd flags are not stored in the kernel_handle |
- * or the filesystem node but directly in the FD mapping. |
- */ |
+// Helper function for calling ki_ioctl without having |
+// to construct a va_list. |
+static int ki_ioctl_wrapper(int fd, int request, ...) { |
+ va_list ap; |
+ va_start(ap, request); |
+ int rtn = ki_ioctl(fd, request, ap); |
+ va_end(ap); |
+ return rtn; |
+} |
+ |
+// Helper to verify directory contents using ki_getdents. |
+// Verified that each of the 'count' elements in the 'expected' array |
+// are present in the directory and that no other entries are present. |
+// If count is -1 then no checking is done and enties are printed using |
+// printf. |
+static void CheckDirContents(const char* dirname, const char** expected, |
+ int count) { |
+ int dir = ki_open(dirname, O_RDONLY, 0); |
+ ASSERT_GE(dir, 0); |
+ while (1) { |
+ size_t sz = sizeof(struct dirent) * 10; |
+ char* buf = (char*)alloca(sz); |
+ int rtn = ki_getdents(dir, (struct dirent*)buf, sz); |
+ if (rtn <= 0) |
+ break; |
+ int offset = 0; |
+ while (offset < rtn) { |
+ struct dirent* entry = (struct dirent*)(buf + offset); |
+ offset += entry->d_reclen; |
+ if (count == -1) { |
+ nacl_io_log("directory entry: %s\n", entry->d_name); |
+ continue; |
+ } |
+ int j; |
+ for (j = 0; j < count; j++) { |
+ if (expected[j] && strcmp(expected[j], entry->d_name) == 0) { |
+ expected[j] = NULL; |
+ break; |
+ } |
+ } |
+ if (j == count) { |
+ FAIL() << "Unexpeected entry '" << entry->d_name |
+ << "' in directory: " << dirname; |
+ } |
+ } |
+ } |
+ |
+ ASSERT_EQ(0, ki_close(dir)); |
+ |
+ if (count != -1) { |
+ for (int i = 0; i < count; i++) { |
+ if (expected[i] != NULL) { |
+ FAIL() << "Expected entry '" << expected[i] |
+ << "' not found in directory: " << dirname; |
+ } |
+ } |
+ } |
+} |
+ |
+// Test for fcntl commands F_SETFD and F_GETFD. This |
+// is tested here rather than in the mount_node tests |
+// since the fd flags are not stored in the kernel_handle |
+// or the filesystem node but directly in the FD mapping. |
TEST_F(KernelProxyTest, Fcntl_GETFD) { |
int fd = ki_open("/test", O_RDWR | O_CREAT, 0777); |
ASSERT_NE(-1, fd); |
@@ -121,7 +180,7 @@ TEST_F(KernelProxyTest, FileLeak) { |
for (int file_num = 0; file_num < 4096; file_num++) { |
sprintf(filename, "/foo%i.tmp", file_num++); |
int fd = ki_open(filename, O_WRONLY | O_CREAT, 0777); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
ASSERT_EQ(1, root->ChildCount()); |
ASSERT_EQ(buffer_size, ki_write(fd, garbage, buffer_size)); |
ki_close(fd); |
@@ -237,7 +296,7 @@ TEST_F(KernelProxyTest, SignalSigwinch) { |
TEST_F(KernelProxyTest, Rename) { |
// Create a dummy file |
int file1 = ki_open("/test1.txt", O_RDWR | O_CREAT, 0777); |
- ASSERT_GT(file1, -1); |
+ ASSERT_GE(file1, 0); |
ASSERT_EQ(0, ki_close(file1)); |
// Test the renaming works |
@@ -287,6 +346,31 @@ TEST_F(KernelProxyTest, WorkingDirectory) { |
EXPECT_STREQ("/foo", text); |
} |
+TEST_F(KernelProxyTest, Mkdir) { |
+ ASSERT_EQ(0, ki_mkdir("/foo", S_IREAD | S_IWRITE)); |
+ ASSERT_EQ(-1, ki_mkdir("/foo", S_IREAD | S_IWRITE)); |
+ ASSERT_EQ(EEXIST, errno); |
+ |
+ // Some component of parent directory does not exist |
+ ASSERT_EQ(-1, ki_mkdir("/does_not_exist/foo", S_IREAD | S_IWRITE)); |
+ ASSERT_EQ(ENOENT, errno); |
+ |
+ int fd = ki_open("/filename", O_CREAT | O_RDWR, 0777); |
+ ASSERT_GE(fd, 0); |
+ |
+ // Some component of parent directory is not actually a directory |
+ ASSERT_EQ(-1, ki_mkdir("/filename/foo", S_IREAD | S_IWRITE)); |
+ ASSERT_EQ(ENOTDIR, errno); |
+} |
+ |
+TEST_F(KernelProxyTest, Rmdir) { |
+ ASSERT_EQ(-1, ki_rmdir("/dev/fs")); |
+ ASSERT_EQ(EPERM, errno); |
+ |
+ ASSERT_EQ(-1, ki_rmdir("/foo")); |
+ ASSERT_EQ(ENOENT, errno); |
+} |
+ |
TEST_F(KernelProxyTest, FDPathMapping) { |
char text[1024]; |
@@ -298,26 +382,27 @@ TEST_F(KernelProxyTest, FDPathMapping) { |
ki_chdir("/foo"); |
fd1 = ki_open("/example", O_RDONLY, 0); |
- EXPECT_NE(-1, fd1); |
+ ASSERT_GT(fd1, 0); |
EXPECT_EQ(ki_fchdir(fd1), 0); |
EXPECT_EQ(text, ki_getcwd(text, sizeof(text))); |
EXPECT_STREQ("/example", text); |
EXPECT_EQ(0, ki_chdir("/foo")); |
fd2 = ki_open("../example", O_RDONLY, 0); |
- EXPECT_NE(-1, fd2); |
+ ASSERT_GE(fd2, 0); |
EXPECT_EQ(0, ki_fchdir(fd2)); |
EXPECT_EQ(text, ki_getcwd(text, sizeof(text))); |
EXPECT_STREQ("/example", text); |
EXPECT_EQ(0, ki_chdir("/foo")); |
fd3 = ki_open("../test", O_CREAT | O_RDWR, 0777); |
- EXPECT_NE(-1, fd3); |
+ ASSERT_GE(fd3, 0); |
EXPECT_EQ(-1, ki_fchdir(fd3)); |
EXPECT_EQ(ENOTDIR, errno); |
EXPECT_EQ(0, ki_chdir("/foo")); |
fd4 = ki_open("bar", O_RDONLY, 0); |
+ ASSERT_GE(fd4, 0); |
EXPECT_EQ(0, ki_fchdir(fd4)); |
EXPECT_EQ(text, ki_getcwd(text, sizeof(text))); |
EXPECT_STREQ("/foo/bar", text); |
@@ -328,7 +413,7 @@ TEST_F(KernelProxyTest, FDPathMapping) { |
EXPECT_EQ(0, ki_chdir("/example")); |
fd5 = ki_dup(fd4); |
- ASSERT_GT(fd5, -1); |
+ ASSERT_GE(fd5, 0); |
ASSERT_NE(fd4, fd5); |
EXPECT_EQ(0, ki_fchdir(fd5)); |
EXPECT_EQ(text, ki_getcwd(text, sizeof(text))); |
@@ -343,6 +428,15 @@ TEST_F(KernelProxyTest, FDPathMapping) { |
EXPECT_STREQ("/foo/bar", text); |
} |
+TEST_F(KernelProxyTest, Getdents) { |
+ const char* expected[] = { "..", "." }; |
+ CheckDirContents("/", expected, 2); |
+ |
+ ASSERT_GE(ki_open("/foo", O_RDWR | O_CREAT, 0777), 0); |
+ const char* expected1[] = { "foo", "..", "." }; |
+ CheckDirContents("/", expected1, 3); |
+} |
+ |
TEST_F(KernelProxyTest, BasicReadWrite) { |
char text[1024]; |
int fd1, fd2, fd3; |
@@ -465,7 +559,7 @@ TEST_F(KernelProxyTest, Truncate) { |
TEST_F(KernelProxyTest, Lseek) { |
int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
ASSERT_EQ(9, ki_write(fd, "Some text", 9)); |
ASSERT_EQ(9, ki_lseek(fd, 0, SEEK_CUR)); |
@@ -485,12 +579,12 @@ TEST_F(KernelProxyTest, Lseek) { |
TEST_F(KernelProxyTest, CloseTwice) { |
int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
EXPECT_EQ(9, ki_write(fd, "Some text", 9)); |
int fd2 = ki_dup(fd); |
- ASSERT_GT(fd2, -1); |
+ ASSERT_GE(fd2, 0); |
EXPECT_EQ(0, ki_close(fd)); |
EXPECT_EQ(0, ki_close(fd2)); |
@@ -498,7 +592,7 @@ TEST_F(KernelProxyTest, CloseTwice) { |
TEST_F(KernelProxyTest, Dup) { |
int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
int dup_fd = ki_dup(fd); |
ASSERT_NE(-1, dup_fd); |
@@ -583,7 +677,7 @@ TEST_F(KernelProxyTest, DescriptorAllocationConsistency) { |
// The test makes the assumption at all descriptors |
// open by default are contiguous starting from zero. |
int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
// The next descriptor allocated should follow the first. |
int dup_fd = ki_dup(fd); |
@@ -600,7 +694,7 @@ TEST_F(KernelProxyTest, DescriptorAllocationConsistency) { |
TEST_F(KernelProxyTest, Lstat) { |
int fd = ki_open("/foo", O_CREAT | O_RDWR, 0777); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
ASSERT_EQ(0, ki_mkdir("/bar", S_IRUSR | S_IWUSR)); |
struct stat buf; |
@@ -666,7 +760,7 @@ TEST_F(KernelProxyTest, Fchmod) { |
TEST_F(KernelProxyTest, OpenDirectory) { |
// Opening a directory for read should succeed. |
int fd = ki_open("/", O_RDONLY, 0); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
// Opening a directory for write should fail. |
EXPECT_EQ(-1, ki_open("/", O_RDWR, 0)); |
@@ -677,7 +771,7 @@ TEST_F(KernelProxyTest, OpenDirectory) { |
TEST_F(KernelProxyTest, OpenWithMode) { |
int fd = ki_open("/foo", O_CREAT | O_RDWR, 0723); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
struct stat buf; |
EXPECT_EQ(0, ki_lstat("/foo", &buf)); |
@@ -686,12 +780,12 @@ TEST_F(KernelProxyTest, OpenWithMode) { |
TEST_F(KernelProxyTest, CreateWronlyWithReadOnlyMode) { |
int fd = ki_open("/foo", O_CREAT | O_WRONLY, 0444); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
} |
TEST_F(KernelProxyTest, UseAfterClose) { |
int fd = ki_open("/dummy", O_CREAT | O_WRONLY, 0777); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
EXPECT_EQ(5, ki_write(fd, "hello", 5)); |
EXPECT_EQ(0, ki_close(fd)); |
EXPECT_EQ(-1, ki_write(fd, "hello", 5)); |
@@ -706,7 +800,7 @@ TEST_F(KernelProxyTest, Utimes) { |
times[1].tv_usec = 4000; |
int fd = ki_open("/dummy", O_CREAT | O_WRONLY, 0222); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
EXPECT_EQ(0, ki_close(fd)); |
// utime should work if the file is write-only. |
@@ -745,7 +839,7 @@ TEST_F(KernelProxyTest, Utime) { |
times.modtime = 2000; |
int fd = ki_open("/dummy", O_CREAT | O_WRONLY, 0222); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
EXPECT_EQ(0, ki_close(fd)); |
// utime should work if the file is write-only. |
@@ -780,7 +874,7 @@ TEST_F(KernelProxyTest, Umask) { |
EXPECT_EQ(0, oldmask); |
int fd = ki_open("/foo", O_CREAT | O_RDONLY, 0666); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
ki_close(fd); |
EXPECT_EQ(0, ki_mkdir("/dir", 0777)); |
@@ -852,39 +946,40 @@ class KernelProxyMountTest : public ::testing::Test { |
KernelProxyMountTest_KernelProxy kp_; |
}; |
-// Helper function for calling ki_ioctl without having |
-// to construct a va_list. |
-int ki_ioctl_wrapper(int fd, int request, ...) { |
- va_list ap; |
- va_start(ap, request); |
- int rtn = ki_ioctl(fd, request, ap); |
- va_end(ap); |
- return rtn; |
-} |
- |
} // namespace |
TEST_F(KernelProxyMountTest, MountInit) { |
- int res1 = ki_mount("/", "/mnt1", "initfs", 0, "false,foo=bar"); |
+ ASSERT_EQ(0, ki_mkdir("/mnt1", 0777)); |
+ int res1 = ki_mount("", "/mnt1", "initfs", 0, "false,foo=bar"); |
EXPECT_EQ("bar", g_string_map["foo"]); |
EXPECT_EQ(-1, res1); |
EXPECT_EQ(EINVAL, errno); |
- int res2 = ki_mount("/", "/mnt2", "initfs", 0, "true,bar=foo,x=y"); |
+ ASSERT_EQ(0, ki_mkdir("/mnt2", 0777)); |
+ int res2 = ki_mount("", "/mnt2", "initfs", 0, "true,bar=foo,x=y"); |
EXPECT_NE(-1, res2); |
EXPECT_EQ("y", g_string_map["x"]); |
+ |
+} |
+ |
+TEST_F(KernelProxyMountTest, Passthroughfs) { |
+ ASSERT_EQ(0, ki_mkdir("/passthrough", 0777)); |
+ int res1 = ki_mount("", "/passthrough", "passthroughfs", 0, ""); |
+ EXPECT_NE(-1, res1); |
+ CheckDirContents("/passthrough", NULL, -1); |
} |
TEST_F(KernelProxyMountTest, MountAndIoctl) { |
- ASSERT_EQ(0, ki_mount("/", "/mnt1", "initfs", 0, "")); |
+ ASSERT_EQ(0, ki_mkdir("/mnt1", 0777)); |
+ ASSERT_EQ(0, ki_mount("", "/mnt1", "initfs", 0, "")); |
ASSERT_NE(-1, g_fs_dev); |
char path[100]; |
- snprintf(path, 100, "dev/fs/%d", g_fs_dev); |
+ snprintf(path, 100, "/dev/fs/%d", g_fs_dev); |
int fd = ki_open(path, O_RDONLY, 0); |
- ASSERT_GT(fd, -1); |
+ ASSERT_GE(fd, 0); |
EXPECT_EQ(0, ki_ioctl_wrapper(fd, 0xdeadbeef)); |
EXPECT_EQ(true, g_fs_ioctl_called); |
@@ -897,7 +992,7 @@ static void mount_callback(const char* source, |
const void* data, |
dev_t dev, |
void* user_data) { |
- EXPECT_STREQ("/", source); |
+ EXPECT_STREQ("dummy", source); |
EXPECT_STREQ("/mnt1", target); |
EXPECT_STREQ("initfs", filesystemtype); |
EXPECT_EQ(0, mountflags); |
@@ -911,7 +1006,8 @@ static void mount_callback(const char* source, |
TEST_F(KernelProxyMountTest, MountCallback) { |
bool callback_called = false; |
kp_.SetMountCallback(&mount_callback, &callback_called); |
- ASSERT_EQ(0, ki_mount("/", "/mnt1", "initfs", 0, "")); |
+ ASSERT_EQ(0, ki_mkdir("/mnt1", 0777)); |
+ ASSERT_EQ(0, ki_mount("dummy", "/mnt1", "initfs", 0, "")); |
ASSERT_NE(-1, g_fs_dev); |
EXPECT_EQ(true, callback_called); |
} |
@@ -1002,9 +1098,9 @@ class KernelProxyMMapTest : public ::testing::Test { |
} // namespace |
TEST_F(KernelProxyMMapTest, MMap) { |
- ASSERT_EQ(0, ki_umount("/")); |
- ASSERT_EQ(0, ki_mount("", "/", "mmapfs", 0, NULL)); |
- int fd = ki_open("/file", O_RDWR | O_CREAT, 0777); |
+ ASSERT_EQ(0, ki_mkdir("/mmap", 0777)); |
+ ASSERT_EQ(0, ki_mount("", "/mmap", "mmapfs", 0, NULL)); |
+ int fd = ki_open("/mmap/file", O_RDWR | O_CREAT, 0777); |
ASSERT_NE(-1, fd); |
void* addr1 = ki_mmap(NULL, 0x800, PROT_READ, MAP_PRIVATE, fd, 0); |
@@ -1068,7 +1164,7 @@ class KernelProxyErrorTest : public ::testing::Test { |
void SetUp() { |
ASSERT_EQ(0, ki_push_state_for_testing()); |
ASSERT_EQ(0, ki_init(&kp_)); |
- // Unmount the passthrough FS and mount a testfs. |
+ // Unmount root fs and mount a testfs. |
EXPECT_EQ(0, kp_.umount("/")); |
EXPECT_EQ(0, kp_.mount("", "/", "testfs", 0, NULL)); |
} |