2 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
8 * NaCl tests for simple syscalls
21 #include "native_client/src/include/nacl_assert.h"
22 #include "native_client/src/trusted/service_runtime/include/sys/nacl_syscalls.h"
24 #define PRINT_HEADER 0
25 #define TEXT_LINE_SIZE 1024
28 * TODO(sbc): remove this test once these declarations get added to the prebuilt
32 extern "C" int gethostname(char *name, size_t len);
33 extern "C" int utimes(const char *filename, const struct timeval times[2]);
37 * function failed(testname, msg)
38 * print failure message and exit with a return code of -1
40 bool failed(const char *testname, const char *msg) {
41 printf("TEST FAILED: %s: %s\n", testname, msg);
46 * function passed(testname, msg)
47 * print success message
49 bool passed(const char *testname, const char *msg) {
50 printf("TEST PASSED: %s: %s\n", testname, msg);
55 * Split filename into basename and dirname.
56 * The argument is modified in place such that it
57 * becomes the dirname and the basename is returned.
59 static char *split_name(char *full_name) {
60 // Strip off the trailing filename
61 char *basename = strrchr(full_name, '/');
62 if (basename == NULL) {
63 basename = strrchr(full_name, '\\');
64 ASSERT_NE_MSG(basename, NULL, "test_file contains no dir seperator");
72 // In case a previous run of this test failed and left the file behind,
73 // remove the file first.
74 // TODO(mseaborn): It would be cleaner to create a guaranteed-empty temp
75 // directory instead of doing this.
76 static void ensure_file_is_absent(const char *filename) {
77 int result = unlink(filename);
79 ASSERT_EQ(errno, ENOENT);
86 * Simple tests follow below. Each test may call one or more
87 * of the functions above. They all have a boolean return value
88 * to indicate success (all tests passed) or failure (one or more
89 * tests failed) Order matters - the parent should call
90 * test1() before test2(), and so on.
93 bool test_sched_yield() {
95 printf("sched_yield failed\n");
101 bool test_sysconf() {
102 // TODO(hamaji): Implement _SC_NPROCESSORS_ONLN for newlib based
103 // non-SFI mode. Note that this test works for unsandboxed mode.
107 rv = sysconf(_SC_NPROCESSORS_ONLN);
109 printf("failed to get nprocs\n");
113 printf("got strange number of processors: %d\n", rv);
116 // test sysconf on an invalid input.
119 printf("succeeded on unsupported\n");
125 // Simple test that chdir returns zero for '.'. chdir gets more
126 // significant testing as part of the getcwd test.
128 int rtn = chdir(".");
129 ASSERT_EQ_MSG(rtn, 0, "chdir() failed");
131 return passed("test_chdir", "all");
134 bool test_mkdir_rmdir(const char *test_file) {
135 // Use a temporary direcotry name alongside the test_file which
137 char dirname[PATH_MAX];
138 strncpy(dirname, test_file, PATH_MAX);
141 ASSERT(strlen(dirname) + 6 < PATH_MAX);
142 strncat(dirname, "tmpdir", 6);
144 // Attempt to remove the directory in case it already exists
145 // from a previous test run.
146 if (rmdir(dirname) != 0)
147 ASSERT_EQ_MSG(errno, ENOENT, "rmdir() failed to cleanup existing dir");
150 char *cwd_rtn = getcwd(cwd, PATH_MAX);
151 ASSERT_EQ_MSG(cwd_rtn, cwd, "getcwd() failed");
153 int rtn = mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR);
154 ASSERT_EQ_MSG(rtn, 0, "mkdir() failed");
156 rtn = rmdir(dirname);
157 ASSERT_EQ_MSG(rtn, 0, "rmdir() failed");
159 rtn = rmdir("This file does not exist");
160 ASSERT_EQ_MSG(rtn, -1, "rmdir() failed to fail");
161 ASSERT_EQ_MSG(errno, ENOENT, "rmdir() failed to generate ENOENT");
163 return passed("test_mkdir_rmdir", "all");
167 char dirname[PATH_MAX] = { '\0' };
168 char newdir[PATH_MAX] = { '\0' };
169 char parent[PATH_MAX] = { '\0' };
171 char *rtn = getcwd(dirname, PATH_MAX);
172 ASSERT_EQ_MSG(rtn, dirname, "getcwd() failed to return dirname");
173 ASSERT_NE_MSG(strlen(dirname), 0, "getcwd() failed to set valid dirname");
175 // Calculate parent folder.
176 strncpy(parent, dirname, PATH_MAX);
177 char *basename_start = strrchr(parent, '/');
178 if (basename_start == NULL) {
179 basename_start = strrchr(parent, '\\');
180 ASSERT_NE_MSG(basename_start, NULL, "test_file contains no dir seperator");
182 basename_start[0] = '\0';
184 int retcode = chdir("..");
185 ASSERT_EQ_MSG(retcode, 0, "chdir() failed");
187 rtn = getcwd(newdir, PATH_MAX);
188 ASSERT_EQ_MSG(rtn, newdir, "getcwd() failed");
190 ASSERT_MSG(strcmp(newdir, parent) == 0, "getcwd() failed after chdir");
191 retcode = chdir(dirname);
192 ASSERT_EQ_MSG(retcode, 0, "chdir() failed");
194 rtn = getcwd(dirname, 2);
195 ASSERT_EQ_MSG(rtn, NULL, "getcwd() failed to fail");
196 ASSERT_EQ_MSG(errno, ERANGE, "getcwd() failed to generate ERANGE");
198 return passed("test_getcwd", "all");
201 bool test_unlink(const char *test_file) {
204 char temp_file[PATH_MAX];
205 snprintf(temp_file, PATH_MAX, "%s.tmp_unlink", test_file);
206 temp_file[PATH_MAX - 1] = '\0';
208 int fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
209 ASSERT_MSG(fd >= 0, "open() failed");
212 ASSERT_EQ_MSG(rtn, 0, "close() failed");
214 rtn = stat(temp_file, &buf);
215 ASSERT_EQ_MSG(rtn, 0, "stat() failed");
217 rtn = unlink(temp_file);
218 ASSERT_EQ_MSG(rtn, 0, "unlink() failed");
220 rtn = stat(temp_file, &buf);
221 ASSERT_NE_MSG(rtn, 0, "unlink() failed to remove file");
223 rtn = unlink(temp_file);
224 ASSERT_NE_MSG(rtn, 0, "unlink() failed to fail");
226 return passed("test_unlink", "all");
229 bool test_rename(const char *test_file) {
232 char filename1[PATH_MAX];
233 char filename2[PATH_MAX];
234 snprintf(filename1, PATH_MAX, "%s.tmp1", test_file);
235 snprintf(filename2, PATH_MAX, "%s.tmp2", test_file);
237 // Create a test file and verify that we can stat() it.
238 int fd = open(filename1, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
239 ASSERT_MSG(fd >= 0, "open() failed");
241 ASSERT_EQ_MSG(rtn, 0, "close() failed");
243 rtn = stat(filename1, &buf);
244 ASSERT_EQ_MSG(rtn, 0, "stat() failed");
246 // Rename the test file and verify that the old file is no
247 // longer stat()-able.
248 rtn = rename(filename1, filename2);
249 ASSERT_EQ_MSG(rtn, 0, "rename() failed");
251 rtn = stat(filename2, &buf);
252 ASSERT_EQ_MSG(rtn, 0, "stat() of new file failed");
254 rtn = stat(filename1, &buf);
255 ASSERT_NE_MSG(rtn, 0, "stat() of old name should fail after rename");
257 ASSERT_EQ(remove(filename2), 0);
258 return passed("test_rename", "all");
261 bool test_link(const char *test_file) {
263 struct stat buf_orig;
264 char link_filename[PATH_MAX];
265 char target_filename[PATH_MAX];
266 snprintf(target_filename, PATH_MAX, "%s.target", test_file);
267 snprintf(link_filename, PATH_MAX, "%s.link", test_file);
269 ensure_file_is_absent(target_filename);
270 ensure_file_is_absent(link_filename);
272 // Create link target with some dummy data
273 int fd = open(target_filename, O_WRONLY | O_CREAT, S_IRWXU);
275 ASSERT_EQ(write(fd, "123", 3), 3);
276 ASSERT_EQ(close(fd), 0);
278 int rtn = link(target_filename, link_filename);
279 if (rtn != 0 && errno == ENOSYS) {
280 // If we get ENOSYS, assume we are on Windows, where link() is expected
282 return passed("test_link", "all");
286 // Verify that the new file is a regular file and that changes to it are
287 // mirrored in the original file.
288 ASSERT_EQ(stat(link_filename, &buf), 0);
289 ASSERT_EQ(stat(target_filename, &buf_orig), 0);
290 ASSERT(S_ISREG(buf.st_mode));
291 ASSERT(S_ISREG(buf_orig.st_mode));
293 ASSERT_EQ(buf_orig.st_size, 3);
294 ASSERT_EQ(buf_orig.st_size, buf.st_size);
296 // Write some bytes to the new file
297 fd = open(link_filename, O_WRONLY);
299 ASSERT_EQ(write(fd, "test", 4), 4);
300 ASSERT_EQ(close(fd), 0);
302 // Verify that the two files are still the same size
303 ASSERT_EQ(stat(link_filename, &buf), 0);
304 ASSERT_EQ(stat(target_filename, &buf_orig), 0);
305 ASSERT(S_ISREG(buf.st_mode));
306 ASSERT(S_ISREG(buf_orig.st_mode));
307 ASSERT_EQ(buf_orig.st_size, buf.st_size);
308 ASSERT_EQ(buf_orig.st_size, 4);
310 ASSERT_EQ(remove(link_filename), 0);
311 ASSERT_EQ(remove(target_filename), 0);
312 return passed("test_link", "all");
315 // This tests symlink/readlink and lstat.
316 bool test_symlinks(const char *test_file) {
317 char dirname[PATH_MAX];
318 char link_filename[PATH_MAX];
321 // Test that lstat of the test_file works
322 ASSERT_EQ(lstat(test_file, &buf), 0);
323 ASSERT_EQ(S_ISREG(buf.st_mode), 1);
325 // Split filename into basename and dirname.
326 strncpy(dirname, test_file, PATH_MAX);
327 char *basename = split_name(dirname);
329 snprintf(link_filename, PATH_MAX, "%s.link", test_file);
331 ensure_file_is_absent(link_filename);
334 int rtn = symlink(basename, link_filename);
335 if (rtn != 0 && errno == ENOSYS) {
336 // If we get ENOSYS, assume we are on Windows, where symlink() and
337 // readlink() are expected to fail.
338 return passed("test_symlinks", "all");
342 // Check the lstat() and stat of the link
343 ASSERT_EQ(lstat(link_filename, &buf), 0);
344 ASSERT_NE_MSG(S_ISLNK(buf.st_mode), 0, "lstat of link failed to be ISLNK");
345 ASSERT_EQ_MSG(S_ISREG(buf.st_mode), 0, "lstat of link should not be ISREG");
347 ASSERT_EQ(stat(link_filename, &buf), 0);
348 ASSERT_EQ_MSG(S_ISLNK(buf.st_mode), 0, "stat of symlink should not ISLNK");
349 ASSERT_NE_MSG(S_ISREG(buf.st_mode), 0, "stat of symlink should report ISREG");
352 char link_dest[PATH_MAX];
353 memset(link_dest, 0x77, sizeof(link_dest));
354 ssize_t result = readlink(link_filename, link_dest, sizeof(link_dest));
355 ASSERT_EQ(result, (ssize_t) strlen(basename));
356 ASSERT_EQ(memcmp(link_dest, basename, result), 0);
357 // readlink() should not write a null terminator.
358 ASSERT_EQ(link_dest[result], 0x77);
360 // Test readlink() with a truncated result.
361 memset(link_dest, 0x77, sizeof(link_dest));
362 result = readlink(link_filename, link_dest, 1);
363 ASSERT_EQ(result, 1);
364 ASSERT_EQ(link_dest[0], basename[0]);
365 // The rest of the buffer should not be modified.
366 for (size_t i = 1; i < sizeof(link_dest); ++i)
367 ASSERT_EQ(link_dest[i], 0x77);
369 // calling symlink again should yield EEXIST.
370 ASSERT_EQ(symlink(test_file, link_filename), -1);
371 ASSERT_EQ(errno, EEXIST);
372 ASSERT_EQ(remove(link_filename), 0);
374 return passed("test_symlinks", "all");
377 bool test_chmod(const char *test_file) {
379 char temp_file[PATH_MAX];
380 snprintf(temp_file, PATH_MAX, "%s.tmp_chmod", test_file);
382 int fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
384 ASSERT_EQ(close(fd), 0);
386 ASSERT_EQ(stat(temp_file, &buf), 0);
387 ASSERT_EQ(buf.st_mode & ~S_IFMT, S_IRUSR | S_IWUSR);
389 // change the file to readonly and verify the change
390 ASSERT_EQ(chmod(temp_file, S_IRUSR), 0);
391 ASSERT_EQ(stat(temp_file, &buf), 0);
392 ASSERT_EQ(buf.st_mode & ~S_IFMT, S_IRUSR);
393 ASSERT(open(temp_file, O_WRONLY) < 0);
395 ASSERT_EQ(remove(temp_file), 0);
396 return passed("test_chmod", "all");
399 bool test_access(const char *test_file) {
400 char temp_access[PATH_MAX];
401 snprintf(temp_access, PATH_MAX, "%s.tmp_access", test_file);
403 ASSERT_EQ(access(test_file, F_OK), 0);
404 ASSERT_EQ(access(test_file, R_OK), 0);
405 ASSERT_EQ(access(test_file, W_OK), 0);
407 ASSERT_EQ(access(temp_access, F_OK), -1);
408 ASSERT_EQ(access(temp_access, R_OK), -1);
409 ASSERT_EQ(access(temp_access, W_OK), -1);
412 * We can't test the X bit here since it's not consistent across platforms.
413 * On win32 there is no equivalent so we always return true. On Mac/Linux
414 * the underlying X bit is reported.
416 // ASSERT_EQ(access(test_file, X_OK), -1);
417 // ASSERT_EQ(access(temp_access, X_OK), -1);
419 // Create a read-only file
420 int fd = open(temp_access, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR);
422 ASSERT_EQ(close(fd), 0);
424 ASSERT_EQ(access(temp_access, F_OK), 0);
425 ASSERT_EQ(access(temp_access, R_OK), 0);
426 ASSERT_EQ(access(temp_access, W_OK), -1);
427 ASSERT_EQ(remove(temp_access), 0);
429 return passed("test_access", "all");
432 bool test_utimes(const char *test_file) {
433 // TODO(mseaborn): Implement utimes for unsandboxed mode.
436 struct timeval times[2];
437 // utimes() is currently not implemented and should always
439 ASSERT_EQ(utimes("dummy", times), -1);
440 ASSERT_EQ(errno, ENOSYS);
441 return passed("test_utimes", "all");
444 bool test_truncate(const char *test_file) {
445 char temp_file[PATH_MAX];
446 snprintf(temp_file, PATH_MAX, "%s.tmp_truncate", test_file);
449 char read_buffer[200];
451 for (size_t i = 0; i < sizeof(buffer); i++)
454 // Write 100 sequential chars to the test file.
455 int fd = open(temp_file, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
457 ASSERT_EQ(100, write(fd, buffer, 100));
458 ASSERT_EQ(0, close(fd));
460 ASSERT_EQ(stat(temp_file, &buf), 0);
461 ASSERT_EQ(buf.st_size, 100);
463 // truncate the file beyond its current length
464 ASSERT_EQ(truncate(temp_file, 200), 0);
465 ASSERT_EQ(stat(temp_file, &buf), 0);
466 ASSERT_EQ(buf.st_size, 200);
468 // Verify the new content, which should not be 100
469 // bytes of sequential chars and 100 bytes of '\0'
470 fd = open(temp_file, O_RDONLY);
472 ASSERT_EQ(read(fd, read_buffer, 200), 200);
473 ASSERT_EQ(memcmp(read_buffer, buffer, 100), 0);
474 for (int i = 100; i < 200; i++)
475 ASSERT_EQ(read_buffer[i], 0);
476 ASSERT_EQ(0, close(fd));
478 // Now truncate the file to a size smaller than the
480 ASSERT_EQ(truncate(temp_file, 50), 0);
481 ASSERT_EQ(stat(temp_file, &buf), 0);
482 ASSERT_EQ(buf.st_size, 50);
484 fd = open(temp_file, O_RDONLY);
486 ASSERT_EQ(read(fd, read_buffer, 50), 50);
487 ASSERT_EQ(memcmp(read_buffer, buffer, 50), 0);
488 ASSERT_EQ(0, close(fd));
490 ASSERT_EQ(remove(temp_file), 0);
491 return passed("test_truncate", "all");
494 // open() returns the new file descriptor, or -1 if an error occurred
495 bool test_open(const char *test_file) {
497 const char *testname = "test_open";
500 fd = open(test_file, O_RDONLY);
502 return failed(testname, "open(test_file, O_RDONLY)");
506 // file does not exist, flags OK
507 fd = open("testdata/file_none.txt", O_RDONLY);
509 return failed(testname, "open(testdata/file_none.txt, O_RDONLY)");
510 // no such file or directory
512 return failed(testname, "ENOENT != errno");
515 // file OK, flags OK, mode OK
516 fd = open(test_file, O_WRONLY, S_IRUSR);
518 return failed(testname, "open(test_file, O_WRONLY, S_IRUSR)");
522 fd = open(test_file, O_RDWR, S_IRUSR, O_APPEND);
524 return failed(testname, "open(test_file, O_RDWR, S_IRUSR, O_APPEND)");
528 fd = open(".", O_RDONLY);
530 return failed(testname, "open(., O_RDONLY)");
534 // directory does not exist
535 fd = open("nosuchdir", O_RDONLY);
537 return failed(testname, "open(nosuchdir, O_RDONLY)");
538 // no such file or directory
540 return failed(testname, "ENOENT != errno");
543 return passed(testname, "all");
546 bool test_stat(const char *test_file) {
549 // Test incoming test_file for read and write permission.
550 ASSERT_EQ(stat(test_file, &buf), 0);
551 ASSERT_MSG(buf.st_mode & S_IRUSR, "stat() failed to report S_IRUSR");
552 ASSERT_MSG(buf.st_mode & S_IWUSR, "stat() failed to report S_IWUSR");
554 // Test fstat and compare the result with the result of stat.
555 int fd = open(test_file, O_RDONLY);
558 int rc = fstat(fd, &buf2);
560 ASSERT_EQ(buf.st_dev, buf2.st_dev);
561 ASSERT_EQ(buf.st_mode, buf2.st_mode);
562 ASSERT_EQ(buf.st_nlink, buf2.st_nlink);
563 ASSERT_EQ(buf.st_uid, buf2.st_uid);
564 ASSERT_EQ(buf.st_gid, buf2.st_gid);
565 ASSERT_EQ(buf.st_rdev, buf2.st_rdev);
566 ASSERT_EQ(buf.st_size, buf2.st_size);
567 ASSERT_EQ(buf.st_blksize, buf2.st_blksize);
568 ASSERT_EQ(buf.st_blocks, buf2.st_blocks);
569 // Do not check st_atime as it seems to be updated by open or fstat
571 ASSERT_EQ(buf.st_mtime, buf2.st_mtime);
572 ASSERT_EQ(buf.st_ctime, buf2.st_ctime);
576 // An invalid fstat call.
578 ASSERT_EQ(fstat(-1, &buf2), -1);
579 ASSERT_EQ(errno, EBADF);
581 // Test a new read-only file
582 // The current unlink() implemenation in the sel_ldr for Windows
583 // doesn't support removing read-only files.
584 // TODO(sbc): enable this part of the test once this gets fixed.
586 char buffer[PATH_MAX];
587 snprintf(buffer, PATH_MAX, "%s.readonly", test_file);
588 buffer[PATH_MAX - 1] = '\0';
590 ASSERT_EQ(stat(buffer, &buf), -1);
591 int fd = open(buffer, O_RDWR | O_CREAT, S_IRUSR);
593 ASSERT_EQ(close(fd), 0);
594 ASSERT_EQ(stat(buffer, &buf), 0);
595 ASSERT_MSG(buf.st_mode & S_IRUSR, "stat() failed to report S_IRUSR");
596 ASSERT_MSG(!(buf.st_mode & S_IWUSR), "S_IWUSR report for a read-only file");
599 // Windows doesn't support the concept of write only files,
600 // so we can't test this case.
602 return passed("test_stat", "all");
605 // close() returns 0 on success, -1 on error
606 bool test_close(const char *test_file) {
609 const char *testname = "test_close";
612 fd = open(test_file, O_RDWR);
614 return failed(testname, "open(test_file, O_RDWR)");
617 return failed(testname, "close(test_file, O_RDWR)");
620 fd = open(test_file, O_RDWR);
622 return failed(testname, "open(test_file, O_RDWR)");
623 // close on wrong fd not OK
625 ret_val = close(fd+1);
627 return failed(testname, "close(fd+1)");
630 return failed(testname, "EBADF != errno");
633 return failed(testname, "close(test_file, O_RDWR)");
636 fd = open("file_none.txt", O_WRONLY);
638 return failed(testname, "open(file_none.txt, O_WRONLY)");
642 return failed(testname, "close(file_none.txt, O_WRONLY)");
645 return failed(testname, "EBADF != errno");
648 // Linux's open() (unsandboxed) does not allow O_RDWR on a directory.
649 // TODO(mseaborn): sel_ldr should reject O_RDWR on a directory too.
651 fd = open(".", O_RDWR);
653 return failed(testname, "open(., O_RDWR)");
656 return failed(testname, "close(., O_RDWR)");
660 fd = open("nosuchdir", O_RDWR);
662 return failed(testname, "open(nosuchdir, O_RDWR)");
666 return failed(testname, "close(nosuchdir, O_RDWR)");
669 return failed(testname, "EBADF != errno");
671 return passed(testname, "all");
674 // read() returns the number of bytes read on success (0 indicates end
675 // of file), -1 on error
676 bool test_read(const char *test_file) {
680 const char *testname = "test_read";
682 fd = open(test_file, O_RDONLY);
684 return failed(testname, "open(test_file, O_RDONLY)");
686 // fd OK, buffer OK, count OK
687 ret_val = read(fd, out_char, 1);
689 return failed(testname, "read(fd, out_char, 1)");
692 // fd not OK, buffer OK, count OK
693 ret_val = read(-1, out_char, 1);
695 return failed(testname, "read(-1, out_char, 1)");
698 return failed(testname, "EBADF != errno");
701 // fd OK, buffer OK, count not OK
702 // Linux's read() (unsandboxed) does not reject this buffer size.
704 ret_val = read(fd, out_char, -1);
706 return failed(testname, "read(fd, out_char, -1)");
708 ASSERT_EQ(errno, EFAULT);
710 return failed(testname, "EFAULT != errno");
714 // fd not OK, buffer OK, count not OK
715 ret_val = read(-1, out_char, -1);
717 return failed(testname, "read(-1, out_char, -1)");
720 // Under qemu-arm, this read() call returns EFAULT.
721 if (EBADF != errno && EFAULT != errno)
722 return failed(testname, "errno is not EBADF or EFAULT");
725 return failed(testname, "EBADF != errno");
728 // fd OK, buffer OK, count 0
729 ret_val = read(fd, out_char, 0);
731 return failed(testname, "read(fd, out_char, 0)");
733 // read 10, but only 3 are left
734 ret_val = read(fd, out_char, 10);
736 return failed(testname, "read(fd, out_char, 10)");
739 ret_val = read(fd, out_char, 10);
741 return failed(testname, "read(fd, out_char, 10)");
744 return passed(testname, "all");
747 // write() returns the number of bytes written on success, -1 on error
748 bool test_write(const char *test_file) {
751 char out_char[] = "12";
752 const char *testname = "test_write";
754 fd = open(test_file, O_WRONLY);
756 return failed(testname, "open(test_file, O_WRONLY)");
759 ret_val = write(fd, out_char, 2);
761 return failed(testname, "write(fd, out_char, 2)");
765 // Linux's write() (unsandboxed) does not reject this buffer size.
767 ret_val = write(fd, out_char, -1);
769 return failed(testname, "write(fd, out_char, -1)");
772 return failed(testname, "EFAULT != errno");
777 ret_val = write(-1, out_char, 2);
779 return failed(testname, "write(-1, out_char, 2)");
782 return failed(testname, "EBADF != errno");
785 return passed(testname, "all");
788 // lseek returns the resulting offset location in bytes from the
789 // beginning of the file, -1 on error
790 bool test_lseek(const char *test_file) {
794 const char *testname = "test_lseek";
796 fd = open(test_file, O_RDWR);
798 return failed(testname, "open(test_file, O_RDWR)");
800 ret_val = lseek(fd, 2, SEEK_SET);
802 return failed(testname, "lseek(fd, 2, SEEK_SET)");
805 ret_val = lseek(-1, 1, SEEK_SET);
807 return failed(testname, "lseek(-1, 1, SEEK_SET)");
810 return failed(testname, "EBADF != errno");
812 ret_val = read(fd, &out_char, 1);
813 if ((ret_val != 1) || (out_char != '3'))
814 return failed(testname, "read(fd, &out_char, 1) #1");
816 ret_val = lseek(fd, 1, SEEK_CUR);
818 return failed(testname, "lseek(fd, 1, SEEK_CUR)");
820 ret_val = read(fd, &out_char, 1);
821 if ((ret_val != 1) || (out_char != '5'))
822 return failed(testname, "read(fd, &out_char, 1) #2");
824 ret_val = lseek(fd, -1, SEEK_CUR);
826 return failed(testname, "lseek(fd, -1, SEEK_CUR)");
828 ret_val = read(fd, &out_char, 1);
829 if ((ret_val != 1) || (out_char != '5'))
830 return failed(testname, "read(fd, &out_char, 1) #3");
832 ret_val = lseek(fd, -2, SEEK_END);
834 return failed(testname, "lseek(fd, -2, SEEK_END)");
836 ret_val = read(fd, &out_char, 1);
837 if ((ret_val != 1) || (out_char != '4'))
838 return failed(testname, "read(fd, &out_char, 1) #4");
840 ret_val = lseek(fd, 4, SEEK_END);
841 // lseek allows for positioning beyond the EOF
843 return failed(testname, "lseek(fd, 4, SEEK_END)");
845 ret_val = lseek(fd, 4, SEEK_SET);
847 return failed(testname, "lseek(fd, 4, SEEK_SET)");
850 ret_val = lseek(fd, 4, SEEK_END + 3);
852 return failed(testname, "lseek(fd, 4, SEEK_END + 3)");
855 return failed(testname, "EINVAL != errno");
858 ret_val = lseek(fd, -40, SEEK_SET);
860 return failed(testname, "lseek(fd, -40, SEEK_SET)");
863 return failed(testname, "EINVAL != errno");
865 ret_val = read(fd, &out_char, 1);
866 if ((ret_val != 1) || (out_char == '4'))
867 return failed(testname, "read(fd, &out_char, 1) #5");
870 return passed(testname, "all");
873 bool test_readdir(const char *test_file) {
874 // TODO(mseaborn): Implement listing directories for unsandboxed mode.
878 // Read the directory containing the test file
880 // Split filename into basename and dirname.
881 char dirname[PATH_MAX];
882 strncpy(dirname, test_file, PATH_MAX);
883 char *basename = split_name(dirname);
885 // Read the directory listing and verify that the test_file is
888 DIR *d = opendir(dirname);
889 ASSERT_NE_MSG(d, NULL, "opendir failed");
896 if (!strcmp(ent->d_name, basename))
900 ASSERT_EQ_MSG(1, found, "failed to find test file in directory listing");
902 // Rewind directory and verify that the number of elements
903 // matches the previous count.
907 ASSERT_EQ_MSG(0, count, "readdir after rewinddir was inconsistent");
909 ASSERT_EQ(0, closedir(d));
910 return passed("test_readdir", "all");
913 // isatty returns 1 for TTY descriptors and 0 on error (setting errno)
914 bool test_isatty(const char *test_file) {
915 // TODO(mseaborn): Implement isatty() for unsandboxed mode.
916 // We need to write two if-statements two avoid clang's warning.
921 // TODO(sbc): isatty() in glibc is not yet hooked up to the IRT
922 // interfaces. Remove this conditional once this gets addressed:
923 // https://code.google.com/p/nativeclient/issues/detail?id=3709
924 #if defined(__GLIBC__)
928 // Open a regular file that check that it is not a tty.
929 int fd = open(test_file, O_RDONLY);
930 ASSERT_NE_MSG(fd, -1, "open() failed");
932 ASSERT_EQ_MSG(isatty(fd), 0, "isatty returned non-zero");
933 ASSERT_EQ_MSG(errno, ENOTTY, "isatty failed to set errno to ENOTTY");
936 // Verify that isatty() on closed file returns 0 and sets errno to EBADF
938 ASSERT_EQ_MSG(isatty(fd), 0, "isatty returned non-zero");
939 ASSERT_EQ_MSG(errno, EBADF, "isatty failed to set errno to EBADF");
941 // On Linux opening /dev/ptmx always returns a TTY file descriptor.
942 fd = open("/dev/ptmx", O_RDWR);
945 ASSERT_EQ(isatty(fd), 1);
950 return passed("test_isatty", "all");
954 * Not strictly speaking a syscall, but we have a 'fake' implementation
955 * that we want to test.
957 bool test_gethostname() {
959 ASSERT_EQ(gethostname(hostname, 1), -1);
961 // glibc only provides a stub gethostbyname() that returns
962 // ENOSYS in all cases.
963 ASSERT_EQ(errno, ENOSYS);
965 ASSERT_EQ(errno, ENAMETOOLONG);
968 ASSERT_EQ(gethostname(hostname, 256), 0);
970 ASSERT_EQ(strcmp(hostname, "naclhost"), 0);
972 return passed("test_gethostname", "all");
976 * function testSuite()
978 * Run through a complete sequence of file tests.
980 * returns true if all tests succeed. false if one or more fail.
983 bool testSuite(const char *test_file) {
985 // The order of executing these tests matters!
986 ret &= test_sched_yield();
987 ret &= test_sysconf();
988 ret &= test_stat(test_file);
989 ret &= test_open(test_file);
990 ret &= test_close(test_file);
991 ret &= test_read(test_file);
992 ret &= test_write(test_file);
993 ret &= test_lseek(test_file);
994 ret &= test_readdir(test_file);
995 ret &= test_gethostname();
996 // glibc support for calling syscalls directly, without the IRT, is limited
997 // so we skip certain tests in this case.
998 #if !defined(__GLIBC__) || TESTS_USE_IRT
999 ret &= test_unlink(test_file);
1000 ret &= test_chdir();
1001 ret &= test_mkdir_rmdir(test_file);
1002 ret &= test_getcwd();
1003 ret &= test_mkdir_rmdir(test_file);
1004 ret &= test_isatty(test_file);
1005 ret &= test_rename(test_file);
1006 ret &= test_link(test_file);
1008 ret &= test_symlinks(test_file);
1010 ret &= test_chmod(test_file);
1011 ret &= test_access(test_file);
1013 // TODO(sbc): remove this restriction once glibc's truncate calls
1014 // is hooked up to the IRT dev-filename-0.2 interface:
1015 // https://code.google.com/p/nativeclient/issues/detail?id=3709
1016 #if !defined(__GLIBC__)
1017 ret &= test_truncate(test_file);
1019 ret &= test_utimes(test_file);
1026 * run all tests and call system exit with appropriate value
1027 * 0 - success, all tests passed.
1028 * -1 - one or more tests failed.
1031 int main(const int argc, const char *argv[]) {
1035 printf("Please specify the test file name\n");
1038 // run the full test suite
1039 passed = testSuite(argv[1]);
1042 printf("All tests PASSED\n");
1045 printf("One or more tests FAILED\n");