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]);
34 extern "C" int eaccess(const char *pathname, int mode);
38 * function failed(testname, msg)
39 * print failure message and exit with a return code of -1
41 bool failed(const char *testname, const char *msg) {
42 printf("TEST FAILED: %s: %s\n", testname, msg);
47 * function passed(testname, msg)
48 * print success message
50 bool passed(const char *testname, const char *msg) {
51 printf("TEST PASSED: %s: %s\n", testname, msg);
56 * Split filename into basename and dirname.
57 * The argument is modified in place such that it
58 * becomes the dirname and the basename is returned.
60 static char *split_name(char *full_name) {
61 // Strip off the trailing filename
62 char *basename = strrchr(full_name, '/');
63 if (basename == NULL) {
64 basename = strrchr(full_name, '\\');
65 ASSERT_NE_MSG(basename, NULL, "test_file contains no dir seperator");
73 // In case a previous run of this test failed and left the file behind,
74 // remove the file first.
75 // TODO(mseaborn): It would be cleaner to create a guaranteed-empty temp
76 // directory instead of doing this.
77 static void ensure_file_is_absent(const char *filename) {
78 int result = unlink(filename);
80 ASSERT_EQ(errno, ENOENT);
87 * Simple tests follow below. Each test may call one or more
88 * of the functions above. They all have a boolean return value
89 * to indicate success (all tests passed) or failure (one or more
90 * tests failed) Order matters - the parent should call
91 * test1() before test2(), and so on.
94 bool test_sched_yield() {
96 printf("sched_yield failed\n");
102 bool test_sysconf() {
103 // TODO(hamaji): Implement _SC_NPROCESSORS_ONLN for newlib based
104 // non-SFI mode. Note that this test works for unsandboxed mode.
108 rv = sysconf(_SC_NPROCESSORS_ONLN);
110 printf("failed to get nprocs\n");
114 printf("got strange number of processors: %d\n", rv);
117 // test sysconf on an invalid input.
120 printf("succeeded on unsupported\n");
126 // Simple test that chdir returns zero for '.'. chdir gets more
127 // significant testing as part of the getcwd test.
129 int rtn = chdir(".");
130 ASSERT_EQ_MSG(rtn, 0, "chdir() failed");
132 return passed("test_chdir", "all");
135 bool test_mkdir_rmdir(const char *test_file) {
136 // Use a temporary direcotry name alongside the test_file which
138 char dirname[PATH_MAX];
139 strncpy(dirname, test_file, PATH_MAX);
142 ASSERT(strlen(dirname) + 6 < PATH_MAX);
143 strncat(dirname, "tmpdir", 6);
145 // Attempt to remove the directory in case it already exists
146 // from a previous test run.
147 if (rmdir(dirname) != 0)
148 ASSERT_EQ_MSG(errno, ENOENT, "rmdir() failed to cleanup existing dir");
151 char *cwd_rtn = getcwd(cwd, PATH_MAX);
152 ASSERT_EQ_MSG(cwd_rtn, cwd, "getcwd() failed");
154 int rtn = mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR);
155 ASSERT_EQ_MSG(rtn, 0, "mkdir() failed");
157 rtn = rmdir(dirname);
158 ASSERT_EQ_MSG(rtn, 0, "rmdir() failed");
160 rtn = rmdir("This file does not exist");
161 ASSERT_EQ_MSG(rtn, -1, "rmdir() failed to fail");
162 ASSERT_EQ_MSG(errno, ENOENT, "rmdir() failed to generate ENOENT");
164 return passed("test_mkdir_rmdir", "all");
168 char dirname[PATH_MAX] = { '\0' };
169 char newdir[PATH_MAX] = { '\0' };
170 char parent[PATH_MAX] = { '\0' };
172 char *rtn = getcwd(dirname, PATH_MAX);
173 ASSERT_EQ_MSG(rtn, dirname, "getcwd() failed to return dirname");
174 ASSERT_NE_MSG(strlen(dirname), 0, "getcwd() failed to set valid dirname");
176 // Calculate parent folder.
177 strncpy(parent, dirname, PATH_MAX);
178 char *basename_start = strrchr(parent, '/');
179 if (basename_start == NULL) {
180 basename_start = strrchr(parent, '\\');
181 ASSERT_NE_MSG(basename_start, NULL, "test_file contains no dir seperator");
183 basename_start[0] = '\0';
185 int retcode = chdir("..");
186 ASSERT_EQ_MSG(retcode, 0, "chdir() failed");
188 rtn = getcwd(newdir, PATH_MAX);
189 ASSERT_EQ_MSG(rtn, newdir, "getcwd() failed");
191 ASSERT_MSG(strcmp(newdir, parent) == 0, "getcwd() failed after chdir");
192 retcode = chdir(dirname);
193 ASSERT_EQ_MSG(retcode, 0, "chdir() failed");
195 rtn = getcwd(dirname, 2);
196 ASSERT_EQ_MSG(rtn, NULL, "getcwd() failed to fail");
197 ASSERT_EQ_MSG(errno, ERANGE, "getcwd() failed to generate ERANGE");
199 return passed("test_getcwd", "all");
202 bool test_unlink(const char *test_file) {
205 char temp_file[PATH_MAX];
206 snprintf(temp_file, PATH_MAX, "%s.tmp_unlink", test_file);
207 temp_file[PATH_MAX - 1] = '\0';
209 int fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
210 ASSERT_MSG(fd >= 0, "open() failed");
213 ASSERT_EQ_MSG(rtn, 0, "close() failed");
215 rtn = stat(temp_file, &buf);
216 ASSERT_EQ_MSG(rtn, 0, "stat() failed");
218 rtn = unlink(temp_file);
219 ASSERT_EQ_MSG(rtn, 0, "unlink() failed");
221 rtn = stat(temp_file, &buf);
222 ASSERT_NE_MSG(rtn, 0, "unlink() failed to remove file");
224 rtn = unlink(temp_file);
225 ASSERT_NE_MSG(rtn, 0, "unlink() failed to fail");
227 return passed("test_unlink", "all");
230 bool test_rename(const char *test_file) {
233 char filename1[PATH_MAX];
234 char filename2[PATH_MAX];
235 snprintf(filename1, PATH_MAX, "%s.tmp1", test_file);
236 snprintf(filename2, PATH_MAX, "%s.tmp2", test_file);
238 // Create a test file and verify that we can stat() it.
239 int fd = open(filename1, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
240 ASSERT_MSG(fd >= 0, "open() failed");
242 ASSERT_EQ_MSG(rtn, 0, "close() failed");
244 rtn = stat(filename1, &buf);
245 ASSERT_EQ_MSG(rtn, 0, "stat() failed");
247 // Rename the test file and verify that the old file is no
248 // longer stat()-able.
249 rtn = rename(filename1, filename2);
250 ASSERT_EQ_MSG(rtn, 0, "rename() failed");
252 rtn = stat(filename2, &buf);
253 ASSERT_EQ_MSG(rtn, 0, "stat() of new file failed");
255 rtn = stat(filename1, &buf);
256 ASSERT_NE_MSG(rtn, 0, "stat() of old name should fail after rename");
258 ASSERT_EQ(remove(filename2), 0);
259 return passed("test_rename", "all");
262 bool test_link(const char *test_file) {
264 struct stat buf_orig;
265 char link_filename[PATH_MAX];
266 char target_filename[PATH_MAX];
267 snprintf(target_filename, PATH_MAX, "%s.target", test_file);
268 snprintf(link_filename, PATH_MAX, "%s.link", test_file);
270 ensure_file_is_absent(target_filename);
271 ensure_file_is_absent(link_filename);
273 // Create link target with some dummy data
274 int fd = open(target_filename, O_WRONLY | O_CREAT, S_IRWXU);
276 ASSERT_EQ(write(fd, "123", 3), 3);
277 ASSERT_EQ(close(fd), 0);
279 int rtn = link(target_filename, link_filename);
280 if (rtn != 0 && errno == ENOSYS) {
281 // If we get ENOSYS, assume we are on Windows, where link() is expected
283 return passed("test_link", "all");
287 // Verify that the new file is a regular file and that changes to it are
288 // mirrored in the original file.
289 ASSERT_EQ(stat(link_filename, &buf), 0);
290 ASSERT_EQ(stat(target_filename, &buf_orig), 0);
291 ASSERT(S_ISREG(buf.st_mode));
292 ASSERT(S_ISREG(buf_orig.st_mode));
294 ASSERT_EQ(buf_orig.st_size, 3);
295 ASSERT_EQ(buf_orig.st_size, buf.st_size);
297 // Write some bytes to the new file
298 fd = open(link_filename, O_WRONLY);
300 ASSERT_EQ(write(fd, "test", 4), 4);
301 ASSERT_EQ(close(fd), 0);
303 // Verify that the two files are still the same size
304 ASSERT_EQ(stat(link_filename, &buf), 0);
305 ASSERT_EQ(stat(target_filename, &buf_orig), 0);
306 ASSERT(S_ISREG(buf.st_mode));
307 ASSERT(S_ISREG(buf_orig.st_mode));
308 ASSERT_EQ(buf_orig.st_size, buf.st_size);
309 ASSERT_EQ(buf_orig.st_size, 4);
311 ASSERT_EQ(remove(link_filename), 0);
312 ASSERT_EQ(remove(target_filename), 0);
313 return passed("test_link", "all");
316 // This tests symlink/readlink and lstat.
317 bool test_symlinks(const char *test_file) {
318 char dirname[PATH_MAX];
319 char link_filename[PATH_MAX];
322 // Test that lstat of the test_file works
323 ASSERT_EQ(lstat(test_file, &buf), 0);
324 ASSERT_EQ(S_ISREG(buf.st_mode), 1);
326 // Split filename into basename and dirname.
327 strncpy(dirname, test_file, PATH_MAX);
328 char *basename = split_name(dirname);
330 snprintf(link_filename, PATH_MAX, "%s.link", test_file);
332 ensure_file_is_absent(link_filename);
335 int rtn = symlink(basename, link_filename);
336 if (rtn != 0 && errno == ENOSYS) {
337 // If we get ENOSYS, assume we are on Windows, where symlink() and
338 // readlink() are expected to fail.
339 return passed("test_symlinks", "all");
343 // Check the lstat() and stat of the link
344 ASSERT_EQ(lstat(link_filename, &buf), 0);
345 ASSERT_NE_MSG(S_ISLNK(buf.st_mode), 0, "lstat of link failed to be ISLNK");
346 ASSERT_EQ_MSG(S_ISREG(buf.st_mode), 0, "lstat of link should not be ISREG");
348 ASSERT_EQ(stat(link_filename, &buf), 0);
349 ASSERT_EQ_MSG(S_ISLNK(buf.st_mode), 0, "stat of symlink should not ISLNK");
350 ASSERT_NE_MSG(S_ISREG(buf.st_mode), 0, "stat of symlink should report ISREG");
353 char link_dest[PATH_MAX];
354 memset(link_dest, 0x77, sizeof(link_dest));
355 ssize_t result = readlink(link_filename, link_dest, sizeof(link_dest));
356 ASSERT_EQ(result, (ssize_t) strlen(basename));
357 ASSERT_EQ(memcmp(link_dest, basename, result), 0);
358 // readlink() should not write a null terminator.
359 ASSERT_EQ(link_dest[result], 0x77);
361 // Test readlink() with a truncated result.
362 memset(link_dest, 0x77, sizeof(link_dest));
363 result = readlink(link_filename, link_dest, 1);
364 ASSERT_EQ(result, 1);
365 ASSERT_EQ(link_dest[0], basename[0]);
366 // The rest of the buffer should not be modified.
367 for (size_t i = 1; i < sizeof(link_dest); ++i)
368 ASSERT_EQ(link_dest[i], 0x77);
370 // calling symlink again should yield EEXIST.
371 ASSERT_EQ(symlink(test_file, link_filename), -1);
372 ASSERT_EQ(errno, EEXIST);
373 ASSERT_EQ(remove(link_filename), 0);
375 return passed("test_symlinks", "all");
378 bool test_chmod(const char *test_file) {
380 char temp_file[PATH_MAX];
381 snprintf(temp_file, PATH_MAX, "%s.tmp_chmod", test_file);
383 int fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
385 ASSERT_EQ(close(fd), 0);
387 ASSERT_EQ(stat(temp_file, &buf), 0);
388 ASSERT_EQ(buf.st_mode & ~S_IFMT, S_IRUSR | S_IWUSR);
390 // change the file to readonly and verify the change
391 ASSERT_EQ(chmod(temp_file, S_IRUSR), 0);
392 ASSERT_EQ(stat(temp_file, &buf), 0);
393 ASSERT_EQ(buf.st_mode & ~S_IFMT, S_IRUSR);
394 ASSERT(open(temp_file, O_WRONLY) < 0);
396 ASSERT_EQ(remove(temp_file), 0);
397 return passed("test_chmod", "all");
400 static void test_access_call(const char *path, int mode, int expected_result) {
401 ASSERT_EQ(access(path, mode), expected_result);
402 ASSERT_EQ(eaccess(path, mode), expected_result);
405 bool test_access(const char *test_file) {
406 char temp_access[PATH_MAX];
407 snprintf(temp_access, PATH_MAX, "%s.tmp_access", test_file);
409 test_access_call(test_file, F_OK, 0);
410 test_access_call(test_file, R_OK, 0);
411 test_access_call(test_file, W_OK, 0);
413 test_access_call(temp_access, F_OK, -1);
414 test_access_call(temp_access, R_OK, -1);
415 test_access_call(temp_access, W_OK, -1);
418 * We can't test the X bit here since it's not consistent across platforms.
419 * On win32 there is no equivalent so we always return true. On Mac/Linux
420 * the underlying X bit is reported.
422 // test_access_call(test_file, X_OK, -1);
423 // test_access_call(temp_access, X_OK, -1);
425 // Create a read-only file
426 int fd = open(temp_access, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR);
428 ASSERT_EQ(close(fd), 0);
430 test_access_call(temp_access, F_OK, 0);
431 test_access_call(temp_access, R_OK, 0);
432 test_access_call(temp_access, W_OK, -1);
433 ASSERT_EQ(remove(temp_access), 0);
435 return passed("test_access", "all");
438 bool test_utimes(const char *test_file) {
439 // TODO(mseaborn): Implement utimes for unsandboxed mode.
442 struct timeval times[2];
443 // utimes() is currently not implemented and should always
445 ASSERT_EQ(utimes("dummy", times), -1);
446 ASSERT_EQ(errno, ENOSYS);
447 return passed("test_utimes", "all");
450 bool test_truncate(const char *test_file) {
451 char temp_file[PATH_MAX];
452 snprintf(temp_file, PATH_MAX, "%s.tmp_truncate", test_file);
455 char read_buffer[200];
457 for (size_t i = 0; i < sizeof(buffer); i++)
460 // Write 100 sequential chars to the test file.
461 int fd = open(temp_file, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
463 ASSERT_EQ(100, write(fd, buffer, 100));
464 ASSERT_EQ(0, close(fd));
466 ASSERT_EQ(stat(temp_file, &buf), 0);
467 ASSERT_EQ(buf.st_size, 100);
469 // truncate the file beyond its current length
470 ASSERT_EQ(truncate(temp_file, 200), 0);
471 ASSERT_EQ(stat(temp_file, &buf), 0);
472 ASSERT_EQ(buf.st_size, 200);
474 // Verify the new content, which should not be 100
475 // bytes of sequential chars and 100 bytes of '\0'
476 fd = open(temp_file, O_RDONLY);
478 ASSERT_EQ(read(fd, read_buffer, 200), 200);
479 ASSERT_EQ(memcmp(read_buffer, buffer, 100), 0);
480 for (int i = 100; i < 200; i++)
481 ASSERT_EQ(read_buffer[i], 0);
482 ASSERT_EQ(0, close(fd));
484 // Now truncate the file to a size smaller than the
486 ASSERT_EQ(truncate(temp_file, 50), 0);
487 ASSERT_EQ(stat(temp_file, &buf), 0);
488 ASSERT_EQ(buf.st_size, 50);
490 fd = open(temp_file, O_RDONLY);
492 ASSERT_EQ(read(fd, read_buffer, 50), 50);
493 ASSERT_EQ(memcmp(read_buffer, buffer, 50), 0);
494 ASSERT_EQ(0, close(fd));
496 ASSERT_EQ(remove(temp_file), 0);
497 return passed("test_truncate", "all");
500 // open() returns the new file descriptor, or -1 if an error occurred
501 bool test_open(const char *test_file) {
503 const char *testname = "test_open";
506 fd = open(test_file, O_RDONLY);
508 return failed(testname, "open(test_file, O_RDONLY)");
512 // file does not exist, flags OK
513 fd = open("testdata/file_none.txt", O_RDONLY);
515 return failed(testname, "open(testdata/file_none.txt, O_RDONLY)");
516 // no such file or directory
518 return failed(testname, "ENOENT != errno");
521 // file OK, flags OK, mode OK
522 fd = open(test_file, O_WRONLY, S_IRUSR);
524 return failed(testname, "open(test_file, O_WRONLY, S_IRUSR)");
528 fd = open(test_file, O_RDWR, S_IRUSR, O_APPEND);
530 return failed(testname, "open(test_file, O_RDWR, S_IRUSR, O_APPEND)");
534 fd = open(".", O_RDONLY);
536 return failed(testname, "open(., O_RDONLY)");
540 // directory does not exist
541 fd = open("nosuchdir", O_RDONLY);
543 return failed(testname, "open(nosuchdir, O_RDONLY)");
544 // no such file or directory
546 return failed(testname, "ENOENT != errno");
549 return passed(testname, "all");
552 bool test_stat(const char *test_file) {
555 // Test incoming test_file for read and write permission.
556 ASSERT_EQ(stat(test_file, &buf), 0);
557 ASSERT_MSG(buf.st_mode & S_IRUSR, "stat() failed to report S_IRUSR");
558 ASSERT_MSG(buf.st_mode & S_IWUSR, "stat() failed to report S_IWUSR");
560 // Test fstat and compare the result with the result of stat.
561 int fd = open(test_file, O_RDONLY);
564 int rc = fstat(fd, &buf2);
566 ASSERT_EQ(buf.st_dev, buf2.st_dev);
567 ASSERT_EQ(buf.st_mode, buf2.st_mode);
568 ASSERT_EQ(buf.st_nlink, buf2.st_nlink);
569 ASSERT_EQ(buf.st_uid, buf2.st_uid);
570 ASSERT_EQ(buf.st_gid, buf2.st_gid);
571 ASSERT_EQ(buf.st_rdev, buf2.st_rdev);
572 ASSERT_EQ(buf.st_size, buf2.st_size);
573 ASSERT_EQ(buf.st_blksize, buf2.st_blksize);
574 ASSERT_EQ(buf.st_blocks, buf2.st_blocks);
575 // Do not check st_atime as it seems to be updated by open or fstat
577 ASSERT_EQ(buf.st_mtime, buf2.st_mtime);
578 ASSERT_EQ(buf.st_ctime, buf2.st_ctime);
582 // An invalid fstat call.
584 ASSERT_EQ(fstat(-1, &buf2), -1);
585 ASSERT_EQ(errno, EBADF);
587 // Test a new read-only file
588 // The current unlink() implemenation in the sel_ldr for Windows
589 // doesn't support removing read-only files.
590 // TODO(sbc): enable this part of the test once this gets fixed.
592 char buffer[PATH_MAX];
593 snprintf(buffer, PATH_MAX, "%s.readonly", test_file);
594 buffer[PATH_MAX - 1] = '\0';
596 ASSERT_EQ(stat(buffer, &buf), -1);
597 int fd = open(buffer, O_RDWR | O_CREAT, S_IRUSR);
599 ASSERT_EQ(close(fd), 0);
600 ASSERT_EQ(stat(buffer, &buf), 0);
601 ASSERT_MSG(buf.st_mode & S_IRUSR, "stat() failed to report S_IRUSR");
602 ASSERT_MSG(!(buf.st_mode & S_IWUSR), "S_IWUSR report for a read-only file");
605 // Windows doesn't support the concept of write only files,
606 // so we can't test this case.
608 return passed("test_stat", "all");
611 // close() returns 0 on success, -1 on error
612 bool test_close(const char *test_file) {
615 const char *testname = "test_close";
618 fd = open(test_file, O_RDWR);
620 return failed(testname, "open(test_file, O_RDWR)");
623 return failed(testname, "close(test_file, O_RDWR)");
626 fd = open(test_file, O_RDWR);
628 return failed(testname, "open(test_file, O_RDWR)");
629 // close on wrong fd not OK
631 ret_val = close(fd+1);
633 return failed(testname, "close(fd+1)");
636 return failed(testname, "EBADF != errno");
639 return failed(testname, "close(test_file, O_RDWR)");
642 fd = open("file_none.txt", O_WRONLY);
644 return failed(testname, "open(file_none.txt, O_WRONLY)");
648 return failed(testname, "close(file_none.txt, O_WRONLY)");
651 return failed(testname, "EBADF != errno");
654 // Linux's open() (unsandboxed) does not allow O_RDWR on a directory.
655 // TODO(mseaborn): sel_ldr should reject O_RDWR on a directory too.
657 fd = open(".", O_RDWR);
659 return failed(testname, "open(., O_RDWR)");
662 return failed(testname, "close(., O_RDWR)");
666 fd = open("nosuchdir", O_RDWR);
668 return failed(testname, "open(nosuchdir, O_RDWR)");
672 return failed(testname, "close(nosuchdir, O_RDWR)");
675 return failed(testname, "EBADF != errno");
677 return passed(testname, "all");
680 // read() returns the number of bytes read on success (0 indicates end
681 // of file), -1 on error
682 bool test_read(const char *test_file) {
686 const char *testname = "test_read";
688 fd = open(test_file, O_RDONLY);
690 return failed(testname, "open(test_file, O_RDONLY)");
692 // fd OK, buffer OK, count OK
693 ret_val = read(fd, out_char, 1);
695 return failed(testname, "read(fd, out_char, 1)");
698 // fd not OK, buffer OK, count OK
699 ret_val = read(-1, out_char, 1);
701 return failed(testname, "read(-1, out_char, 1)");
704 return failed(testname, "EBADF != errno");
707 // fd OK, buffer OK, count not OK
708 // Linux's read() (unsandboxed) does not reject this buffer size.
710 ret_val = read(fd, out_char, -1);
712 return failed(testname, "read(fd, out_char, -1)");
714 ASSERT_EQ(errno, EFAULT);
716 return failed(testname, "EFAULT != errno");
720 // fd not OK, buffer OK, count not OK
721 ret_val = read(-1, out_char, -1);
723 return failed(testname, "read(-1, out_char, -1)");
726 // Under qemu-arm, this read() call returns EFAULT.
727 if (EBADF != errno && EFAULT != errno)
728 return failed(testname, "errno is not EBADF or EFAULT");
731 return failed(testname, "EBADF != errno");
734 // fd OK, buffer OK, count 0
735 ret_val = read(fd, out_char, 0);
737 return failed(testname, "read(fd, out_char, 0)");
739 // read 10, but only 3 are left
740 ret_val = read(fd, out_char, 10);
742 return failed(testname, "read(fd, out_char, 10)");
745 ret_val = read(fd, out_char, 10);
747 return failed(testname, "read(fd, out_char, 10)");
750 return passed(testname, "all");
753 // write() returns the number of bytes written on success, -1 on error
754 bool test_write(const char *test_file) {
757 char out_char[] = "12";
758 const char *testname = "test_write";
760 fd = open(test_file, O_WRONLY);
762 return failed(testname, "open(test_file, O_WRONLY)");
765 ret_val = write(fd, out_char, 2);
767 return failed(testname, "write(fd, out_char, 2)");
771 // Linux's write() (unsandboxed) does not reject this buffer size.
773 ret_val = write(fd, out_char, -1);
775 return failed(testname, "write(fd, out_char, -1)");
778 return failed(testname, "EFAULT != errno");
783 ret_val = write(-1, out_char, 2);
785 return failed(testname, "write(-1, out_char, 2)");
788 return failed(testname, "EBADF != errno");
791 return passed(testname, "all");
794 // lseek returns the resulting offset location in bytes from the
795 // beginning of the file, -1 on error
796 bool test_lseek(const char *test_file) {
800 const char *testname = "test_lseek";
802 fd = open(test_file, O_RDWR);
804 return failed(testname, "open(test_file, O_RDWR)");
806 ret_val = lseek(fd, 2, SEEK_SET);
808 return failed(testname, "lseek(fd, 2, SEEK_SET)");
811 ret_val = lseek(-1, 1, SEEK_SET);
813 return failed(testname, "lseek(-1, 1, SEEK_SET)");
816 return failed(testname, "EBADF != errno");
818 ret_val = read(fd, &out_char, 1);
819 if ((ret_val != 1) || (out_char != '3'))
820 return failed(testname, "read(fd, &out_char, 1) #1");
822 ret_val = lseek(fd, 1, SEEK_CUR);
824 return failed(testname, "lseek(fd, 1, SEEK_CUR)");
826 ret_val = read(fd, &out_char, 1);
827 if ((ret_val != 1) || (out_char != '5'))
828 return failed(testname, "read(fd, &out_char, 1) #2");
830 ret_val = lseek(fd, -1, SEEK_CUR);
832 return failed(testname, "lseek(fd, -1, SEEK_CUR)");
834 ret_val = read(fd, &out_char, 1);
835 if ((ret_val != 1) || (out_char != '5'))
836 return failed(testname, "read(fd, &out_char, 1) #3");
838 ret_val = lseek(fd, -2, SEEK_END);
840 return failed(testname, "lseek(fd, -2, SEEK_END)");
842 ret_val = read(fd, &out_char, 1);
843 if ((ret_val != 1) || (out_char != '4'))
844 return failed(testname, "read(fd, &out_char, 1) #4");
846 ret_val = lseek(fd, 4, SEEK_END);
847 // lseek allows for positioning beyond the EOF
849 return failed(testname, "lseek(fd, 4, SEEK_END)");
851 ret_val = lseek(fd, 4, SEEK_SET);
853 return failed(testname, "lseek(fd, 4, SEEK_SET)");
856 ret_val = lseek(fd, 4, SEEK_END + 3);
858 return failed(testname, "lseek(fd, 4, SEEK_END + 3)");
861 return failed(testname, "EINVAL != errno");
864 ret_val = lseek(fd, -40, SEEK_SET);
866 return failed(testname, "lseek(fd, -40, SEEK_SET)");
869 return failed(testname, "EINVAL != errno");
871 ret_val = read(fd, &out_char, 1);
872 if ((ret_val != 1) || (out_char == '4'))
873 return failed(testname, "read(fd, &out_char, 1) #5");
876 return passed(testname, "all");
879 bool test_readdir(const char *test_file) {
880 // TODO(mseaborn): Implement listing directories for unsandboxed mode.
884 // Read the directory containing the test file
886 // Split filename into basename and dirname.
887 char dirname[PATH_MAX];
888 strncpy(dirname, test_file, PATH_MAX);
889 char *basename = split_name(dirname);
891 // Read the directory listing and verify that the test_file is
894 DIR *d = opendir(dirname);
895 ASSERT_NE_MSG(d, NULL, "opendir failed");
902 if (!strcmp(ent->d_name, basename))
906 ASSERT_EQ_MSG(1, found, "failed to find test file in directory listing");
908 // Rewind directory and verify that the number of elements
909 // matches the previous count.
913 ASSERT_EQ_MSG(0, count, "readdir after rewinddir was inconsistent");
915 ASSERT_EQ(0, closedir(d));
916 return passed("test_readdir", "all");
919 // isatty returns 1 for TTY descriptors and 0 on error (setting errno)
920 bool test_isatty(const char *test_file) {
921 // TODO(mseaborn): Implement isatty() for unsandboxed mode.
922 // We need to write two if-statements two avoid clang's warning.
927 // TODO(sbc): isatty() in glibc is not yet hooked up to the IRT
928 // interfaces. Remove this conditional once this gets addressed:
929 // https://code.google.com/p/nativeclient/issues/detail?id=3709
930 #if defined(__GLIBC__)
934 // Open a regular file that check that it is not a tty.
935 int fd = open(test_file, O_RDONLY);
936 ASSERT_NE_MSG(fd, -1, "open() failed");
938 ASSERT_EQ_MSG(isatty(fd), 0, "isatty returned non-zero");
939 ASSERT_EQ_MSG(errno, ENOTTY, "isatty failed to set errno to ENOTTY");
942 // Verify that isatty() on closed file returns 0 and sets errno to EBADF
944 ASSERT_EQ_MSG(isatty(fd), 0, "isatty returned non-zero");
945 ASSERT_EQ_MSG(errno, EBADF, "isatty failed to set errno to EBADF");
947 // On Linux opening /dev/ptmx always returns a TTY file descriptor.
948 fd = open("/dev/ptmx", O_RDWR);
951 ASSERT_EQ(isatty(fd), 1);
956 return passed("test_isatty", "all");
960 * Not strictly speaking a syscall, but we have a 'fake' implementation
961 * that we want to test.
963 bool test_gethostname() {
965 ASSERT_EQ(gethostname(hostname, 1), -1);
967 // glibc only provides a stub gethostbyname() that returns
968 // ENOSYS in all cases.
969 ASSERT_EQ(errno, ENOSYS);
971 ASSERT_EQ(errno, ENAMETOOLONG);
974 ASSERT_EQ(gethostname(hostname, 256), 0);
976 ASSERT_EQ(strcmp(hostname, "naclhost"), 0);
978 return passed("test_gethostname", "all");
982 * function testSuite()
984 * Run through a complete sequence of file tests.
986 * returns true if all tests succeed. false if one or more fail.
989 bool testSuite(const char *test_file) {
991 // The order of executing these tests matters!
992 ret &= test_sched_yield();
993 ret &= test_sysconf();
994 ret &= test_stat(test_file);
995 ret &= test_open(test_file);
996 ret &= test_close(test_file);
997 ret &= test_read(test_file);
998 ret &= test_write(test_file);
999 ret &= test_lseek(test_file);
1000 ret &= test_readdir(test_file);
1001 ret &= test_gethostname();
1002 // glibc support for calling syscalls directly, without the IRT, is limited
1003 // so we skip certain tests in this case.
1004 #if !defined(__GLIBC__) || TESTS_USE_IRT
1005 ret &= test_unlink(test_file);
1006 ret &= test_chdir();
1007 ret &= test_mkdir_rmdir(test_file);
1008 ret &= test_getcwd();
1009 ret &= test_mkdir_rmdir(test_file);
1010 ret &= test_isatty(test_file);
1011 ret &= test_rename(test_file);
1012 ret &= test_link(test_file);
1013 ret &= test_symlinks(test_file);
1014 ret &= test_chmod(test_file);
1015 ret &= test_access(test_file);
1017 // TODO(sbc): remove this restriction once glibc's truncate calls
1018 // is hooked up to the IRT dev-filename-0.2 interface:
1019 // https://code.google.com/p/nativeclient/issues/detail?id=3709
1020 #if !defined(__GLIBC__)
1021 ret &= test_truncate(test_file);
1023 ret &= test_utimes(test_file);
1030 * run all tests and call system exit with appropriate value
1031 * 0 - success, all tests passed.
1032 * -1 - one or more tests failed.
1035 int main(const int argc, const char *argv[]) {
1039 printf("Please specify the test file name\n");
1042 // run the full test suite
1043 passed = testSuite(argv[1]);
1046 printf("All tests PASSED\n");
1049 printf("One or more tests FAILED\n");