Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(944)

Unified Diff: tests/syscalls/syscalls.cc

Issue 1235633004: DON'T USE THIS -- Providing some missing POSIX File syscalls. (Closed) Base URL: https://chromium.googlesource.com/native_client/src/native_client.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tests/syscalls/nacl.scons ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tests/syscalls/syscalls.cc
diff --git a/tests/syscalls/syscalls.cc b/tests/syscalls/syscalls.cc
index 30bd61855efdfd554bd7c8aea089f2d64a882b13..e063c109e9a83f3326a36e30c2fc12980dcbb07d 100644
--- a/tests/syscalls/syscalls.cc
+++ b/tests/syscalls/syscalls.cc
@@ -18,14 +18,17 @@
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <utime.h>
+#include "native_client/src/include/build_config.h"
#include "native_client/src/include/nacl_assert.h"
#include "native_client/src/trusted/service_runtime/nacl_config.h"
+#include "native_client/src/untrusted/nacl/syscall_bindings_trampoline.h"
#define PRINT_HEADER 0
#define TEXT_LINE_SIZE 1024
+bool windows = false;
+
/*
* TODO(sbc): remove this test once these declarations get added to the
* newlib toolchain
@@ -33,8 +36,6 @@
#ifndef __GLIBC__
extern "C" {
int gethostname(char *name, size_t len);
-int utimes(const char *filename, const struct timeval times[2]);
-int utime(const char *filename, const struct utimbuf *times);
int eaccess(const char *pathname, int mode);
}
#endif
@@ -137,8 +138,66 @@ bool test_chdir() {
return passed("test_chdir", "all");
}
+bool test_fchdir() {
+ char dirname[PATH_MAX] = { '\0' };
+ char newdir[PATH_MAX] = { '\0' };
+ char parent[PATH_MAX] = { '\0' };
+ int retcode;
+ int fd;
+ char *rtn = getcwd(dirname, PATH_MAX);
+ ASSERT_EQ_MSG(rtn, dirname, "getcwd() failed");
+
+ // Calculate parent folder.
+ strncpy(parent, dirname, PATH_MAX);
+ char *basename_start;
+ if (windows) {
+ basename_start = strrchr(parent, '\\');
+ } else {
+ basename_start = strrchr(parent, '/');
+ }
+
+ if (basename_start == NULL) {
+ basename_start = strrchr(parent, '\\');
+ ASSERT_NE_MSG(basename_start, NULL, "test_file contains no dir seperator");
+ }
+ basename_start[0] = '\0';
+
+ // Open parent folder
+ fd = open(parent, O_RDONLY | O_DIRECTORY);
+ ASSERT_NE_MSG(fd, -1, "open() failed to open parent directory");
+
+ retcode = NACL_SYSCALL(fchdir)(fd);
+ if (windows) {
+ // TODO(smklein) Update this once fchdir is implemented.
+ ASSERT_NE_MSG(retcode, 0, "fchdir() should have failed");
+ return passed("test_fchdir", "all");
+ } else {
+ ASSERT_EQ_MSG(retcode, 0, "fchdir() failed");
+ }
+
+ rtn = getcwd(newdir, PATH_MAX);
+ ASSERT_EQ_MSG(rtn, newdir, "getcwd() failed");
+
+ ASSERT_MSG(strcmp(newdir, parent) == 0, "getcwd() failed after fchdir");
+
+ ASSERT_EQ_MSG(close(fd), 0, "close() failed");
+
+ // Let's go back to the child directory
+ fd = open(dirname, O_RDONLY | O_DIRECTORY);
+ ASSERT_NE_MSG(fd, -1, "open() failed to open child directory");
+
+ retcode = NACL_SYSCALL(fchdir)(fd);
+ ASSERT_EQ_MSG(retcode, 0, "fchdir() failed");
+
+ rtn = getcwd(newdir, PATH_MAX);
+ ASSERT_EQ_MSG(rtn, newdir, "getcwd() failed");
+
+ ASSERT_MSG(strcmp(newdir, dirname) == 0, "getcwd() failed after fchdir");
+ return passed("test fchdir", "all");
+}
+
bool test_mkdir_rmdir(const char *test_file) {
- // Use a temporary direcotry name alongside the test_file which
+ // Use a temporary directory name alongside the test_file which
// was passed in.
char dirname[PATH_MAX];
strncpy(dirname, test_file, PATH_MAX);
@@ -309,7 +368,7 @@ bool test_link(const char *test_file) {
ASSERT_EQ(close(fd), 0);
int rtn = link(target_filename, link_filename);
- if (rtn != 0 && errno == ENOSYS) {
+ if (rtn != 0 && errno == ENOSYS && windows) {
// If we get ENOSYS, assume we are on Windows, where link() is expected
// to fail.
return passed("test_link", "all");
@@ -365,7 +424,7 @@ bool test_symlinks(const char *test_file) {
// Create this link
int rtn = symlink(basename, link_filename);
- if (rtn != 0 && errno == ENOSYS) {
+ if (rtn != 0 && errno == ENOSYS && windows) {
// If we get ENOSYS, assume we are on Windows, where symlink() and
// readlink() are expected to fail.
return passed("test_symlinks", "all");
@@ -429,6 +488,36 @@ bool test_chmod(const char *test_file) {
return passed("test_chmod", "all");
}
+bool test_fchmod(const char *test_file) {
+ struct stat buf;
+ char temp_file[PATH_MAX];
+ int retcode;
+ snprintf(temp_file, PATH_MAX, "%s.tmp_fchmod", test_file);
+
+ int fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+ ASSERT(fd >= 0);
+
+ ASSERT_EQ(stat(temp_file, &buf), 0);
+ ASSERT_EQ(buf.st_mode & ~S_IFMT, S_IRUSR | S_IWUSR);
+
+ // change the file to readonly and verify the change
+ retcode = NACL_SYSCALL(fchmod)(fd, S_IRUSR);
+ if (windows) {
+ // TODO(smklein) Update this once fchmod is implemented.
+ ASSERT_NE_MSG(retcode, 0, "fchmod() should have failed");
+ return passed("test_fchmod", "all");
+ } else {
+ ASSERT_EQ(retcode, 0);
+ }
+ ASSERT_EQ(stat(temp_file, &buf), 0);
+ ASSERT_EQ(buf.st_mode & ~S_IFMT, S_IRUSR);
+ ASSERT(open(temp_file, O_WRONLY) < 0);
+
+ ASSERT_EQ(close(fd), 0);
+ ASSERT_EQ(remove(temp_file), 0);
+ return passed("test_fchmod", "all");
+}
+
static void test_access_call(const char *path, int mode, int expected_result) {
ASSERT_EQ(access(path, mode), expected_result);
ASSERT_EQ(eaccess(path, mode), expected_result);
@@ -472,28 +561,76 @@ bool test_utimes(const char *test_file) {
if (NONSFI_MODE)
return true;
struct timeval times[2];
- // utimes() is currently not implemented and should always
- // fail with ENOSYS
- ASSERT_EQ(utimes("dummy", times), -1);
- ASSERT_EQ(errno, ENOSYS);
+ // These numbers are close enough to the epoch time. Windows
+ // does not like going back in time.
+ time_t a_sec = 2132067496;
+ time_t m_sec = 2132067497;
+ times[0].tv_sec = a_sec;
+ times[0].tv_usec = 222;
+ times[1].tv_sec = m_sec;
+ times[1].tv_usec = 444;
+ char temp_file[PATH_MAX];
+ snprintf(temp_file, PATH_MAX, "%s.tmp_utimes", test_file);
+ ensure_file_is_absent(temp_file);
+
+ int fd = open(temp_file, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+ ASSERT(fd >= 0);
+ ASSERT_EQ(close(fd), 0);
+
+ // Use the times we generated earlier (and check the second resolution)
+ ASSERT_EQ(NACL_SYSCALL(utimes)(temp_file, times), 0);
+
+ // Verify the actime + modtime.
+ struct stat s;
+ ASSERT_EQ(stat(temp_file, &s), 0);
+ ASSERT_EQ(s.st_atime, a_sec);
+ ASSERT_EQ(s.st_mtime, m_sec);
+
+ // "NULL" should be a valid time. We only check error code status here.
+ ASSERT_EQ(NACL_SYSCALL(utimes)(temp_file, NULL), 0);
return passed("test_utimes", "all");
}
-bool test_utime(const char *test_file) {
- // TODO(mseaborn): Implement utimes for unsandboxed mode.
- if (NONSFI_MODE)
- return true;
- printf("test_utime");
- struct utimbuf times;
- times.actime = 0;
- times.modtime = 0;
- // utimes() is currently not implemented and should always
- // fail with ENOSYS
- printf("test_utime 2");
-
- ASSERT_EQ(utime("dummy", &times), -1);
- ASSERT_EQ(errno, ENOSYS);
- return passed("test_utime", "all");
+bool test_fsync(const char *test_file) {
+ char temp_file[PATH_MAX];
+ snprintf(temp_file, PATH_MAX, "%s.tmp_fsync", test_file);
+
+ char buffer[100];
+ for (size_t i = 0; i < sizeof(buffer); i++)
+ buffer[i] = i;
+
+ // Write 100 sequential chars to the test file.
+ int fd = open(temp_file, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+ ASSERT(fd >= 0);
+ ASSERT_EQ(100, write(fd, buffer, 100));
+
+ // For now, only testing that fsync does not return an error.
+ // This is a weak test -- TODO(smklein) improve it.
+ ASSERT_EQ(0, NACL_SYSCALL(fsync)(fd));
+ ASSERT_EQ(0, close(fd));
+
+ return passed("test_fsync", "all");
+}
+
+bool test_fdatasync(const char *test_file) {
+ char temp_file[PATH_MAX];
+ snprintf(temp_file, PATH_MAX, "%s.tmp_fdatasync", test_file);
+
+ char buffer[100];
+ for (size_t i = 0; i < sizeof(buffer); i++)
+ buffer[i] = i;
+
+ // Write 100 sequential chars to the test file.
+ int fd = open(temp_file, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+ ASSERT(fd >= 0);
+ ASSERT_EQ(100, write(fd, buffer, 100));
+
+ // For now, only testing that fdatasync does not return an error.
+ // This is a weak test -- TODO(smklein) improve it.
+ ASSERT_EQ(0, NACL_SYSCALL(fdatasync)(fd));
+ ASSERT_EQ(0, close(fd));
+
+ return passed("test_fdatasync", "all");
}
bool test_truncate(const char *test_file) {
@@ -546,6 +683,59 @@ bool test_truncate(const char *test_file) {
return passed("test_truncate", "all");
}
+bool test_ftruncate(const char *test_file) {
+ char temp_file[PATH_MAX];
+ snprintf(temp_file, PATH_MAX, "%s.tmp_ftruncate", test_file);
+
+ char buffer[100];
+ char read_buffer[200];
+ struct stat buf;
+ for (size_t i = 0; i < sizeof(buffer); i++)
+ buffer[i] = i;
+
+ // Write 100 sequential chars to the test file.
+ int fd = open(temp_file, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+ ASSERT(fd >= 0);
+ ASSERT_EQ(100, write(fd, buffer, 100));
+
+ ASSERT_EQ(0, close(fd));
+ fd = open(temp_file, O_WRONLY, S_IRUSR | S_IWUSR);
+ ASSERT_EQ(stat(temp_file, &buf), 0);
+ ASSERT_EQ(buf.st_size, 100);
+
+ // ftruncate the file beyond its current length
+ ASSERT_EQ(NACL_SYSCALL(ftruncate)(fd, 200), 0);
+ ASSERT_EQ(0, close(fd));
+ ASSERT_EQ(stat(temp_file, &buf), 0);
+ ASSERT_EQ(buf.st_size, 200);
+
+ // Verify the new content, which should not be 100
+ // bytes of sequential chars and 100 bytes of '\0'
+ fd = open(temp_file, O_RDWR);
+ ASSERT(fd >= 0);
+ ASSERT_EQ(read(fd, read_buffer, 200), 200);
+ ASSERT_EQ(memcmp(read_buffer, buffer, 100), 0);
+ for (int i = 100; i < 200; i++)
+ ASSERT_EQ(read_buffer[i], 0);
+
+ // Now ftruncate the file to a size smaller than the
+ // original
+ ASSERT_EQ(NACL_SYSCALL(ftruncate)(fd, 50), 0);
+ ASSERT_EQ(0, close(fd));
+ ASSERT_EQ(stat(temp_file, &buf), 0);
+ ASSERT_EQ(buf.st_size, 50);
+
+ fd = open(temp_file, O_RDONLY);
+ ASSERT(fd >= 0);
+ ASSERT_EQ(read(fd, read_buffer, 50), 50);
+ ASSERT_EQ(memcmp(read_buffer, buffer, 50), 0);
+ ASSERT_EQ(0, close(fd));
+
+ ASSERT_EQ(remove(temp_file), 0);
+ return passed("test_ftruncate", "all");
+}
+
+
bool test_open_trunc(const char *test_file) {
int fd;
char buffer[100];
@@ -1176,7 +1366,7 @@ bool testSuite(const char *test_file) {
#if !defined(__GLIBC__) || TESTS_USE_IRT
ret &= test_unlink(test_file);
ret &= test_chdir();
- ret &= test_mkdir_rmdir(test_file);
+ ret &= test_fchdir();
ret &= test_getcwd();
ret &= test_mkdir_rmdir(test_file);
ret &= test_isatty(test_file);
@@ -1184,16 +1374,19 @@ bool testSuite(const char *test_file) {
ret &= test_link(test_file);
ret &= test_symlinks(test_file);
ret &= test_chmod(test_file);
+ ret &= test_fchmod(test_file);
ret &= test_access(test_file);
+ ret &= test_fsync(test_file);
+ ret &= test_fdatasync(test_file);
+ ret &= test_utimes(test_file);
#endif
// TODO(sbc): remove this restriction once glibc's truncate calls
// is hooked up to the IRT dev-filename-0.2 interface:
// https://code.google.com/p/nativeclient/issues/detail?id=3709
#if !(defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 9)
ret &= test_truncate(test_file);
+ ret &= test_ftruncate(test_file);
#endif
- ret &= test_utimes(test_file);
- ret &= test_utime(test_file);
return ret;
}
@@ -1208,10 +1401,13 @@ bool testSuite(const char *test_file) {
int main(const int argc, const char *argv[]) {
bool passed;
- if (argc != 2) {
+ if (argc != 3) {
printf("Please specify the test file name\n");
exit(-1);
}
+ if (argv[2][0] == 'w') {
+ windows = true;
+ }
// run the full test suite
passed = testSuite(argv[1]);
« no previous file with comments | « tests/syscalls/nacl.scons ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698