Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / native_client / tests / syscalls / syscalls.cc
1 /*
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.
5  */
6
7 /*
8  * NaCl tests for simple syscalls
9  */
10
11 #include <dirent.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <limits.h>
15 #include <sched.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <unistd.h>
20
21 #include "native_client/src/include/nacl_assert.h"
22 #include "native_client/src/trusted/service_runtime/include/sys/nacl_syscalls.h"
23
24 #define PRINT_HEADER 0
25 #define TEXT_LINE_SIZE 1024
26
27 /*
28  * TODO(sbc): remove this test once these declarations get added to the prebuilt
29  * newlib toolchain
30  */
31 #ifndef __GLIBC__
32 extern "C" int gethostname(char *name, size_t len);
33 extern "C" int utimes(const char *filename, const struct timeval times[2]);
34 #endif
35
36 /*
37  * function failed(testname, msg)
38  *   print failure message and exit with a return code of -1
39  */
40 bool failed(const char *testname, const char *msg) {
41   printf("TEST FAILED: %s: %s\n", testname, msg);
42   return false;
43 }
44
45 /*
46  * function passed(testname, msg)
47  *   print success message
48  */
49 bool passed(const char *testname, const char *msg) {
50   printf("TEST PASSED: %s: %s\n", testname, msg);
51   return true;
52 }
53
54 /*
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.
58  */
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");
65     if (!basename)
66       return NULL;
67   }
68   basename[0] = '\0';
69   return basename + 1;
70 }
71
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);
78   if (result != 0) {
79     ASSERT_EQ(errno, ENOENT);
80   }
81 }
82
83 /*
84  * function test*()
85  *
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.
91  */
92
93 bool test_sched_yield() {
94   if (sched_yield()) {
95     printf("sched_yield failed\n");
96     return false;
97   }
98   return true;
99 }
100
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.
104   if (NONSFI_MODE)
105     return true;
106   int rv;
107   rv = sysconf(_SC_NPROCESSORS_ONLN);
108   if (rv == -1) {
109     printf("failed to get nprocs\n");
110     return false;
111   }
112   if (rv < 1) {
113     printf("got strange number of processors: %d\n", rv);
114     return false;
115   }
116   // test sysconf on an invalid input.
117   rv = sysconf(-1);
118   if (rv != -1) {
119     printf("succeeded on unsupported\n");
120     return false;
121   }
122   return true;
123 }
124
125 // Simple test that chdir returns zero for '.'.  chdir gets more
126 // significant testing as part of the getcwd test.
127 bool test_chdir() {
128   int rtn = chdir(".");
129   ASSERT_EQ_MSG(rtn, 0, "chdir() failed");
130
131   return passed("test_chdir", "all");
132 }
133
134 bool test_mkdir_rmdir(const char *test_file) {
135   // Use a temporary direcotry name alongside the test_file which
136   // was passed in.
137   char dirname[PATH_MAX];
138   strncpy(dirname, test_file, PATH_MAX);
139   split_name(dirname);
140
141   ASSERT(strlen(dirname) + 6 < PATH_MAX);
142   strncat(dirname, "tmpdir", 6);
143
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");
148
149   char cwd[PATH_MAX];
150   char *cwd_rtn = getcwd(cwd, PATH_MAX);
151   ASSERT_EQ_MSG(cwd_rtn, cwd, "getcwd() failed");
152
153   int rtn = mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR);
154   ASSERT_EQ_MSG(rtn, 0, "mkdir() failed");
155
156   rtn = rmdir(dirname);
157   ASSERT_EQ_MSG(rtn, 0, "rmdir() failed");
158
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");
162
163   return passed("test_mkdir_rmdir", "all");
164 }
165
166 bool test_getcwd() {
167   char dirname[PATH_MAX] = { '\0' };
168   char newdir[PATH_MAX] = { '\0' };
169   char parent[PATH_MAX] = { '\0' };
170
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");
174
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");
181   }
182   basename_start[0] = '\0';
183
184   int retcode = chdir("..");
185   ASSERT_EQ_MSG(retcode, 0, "chdir() failed");
186
187   rtn = getcwd(newdir, PATH_MAX);
188   ASSERT_EQ_MSG(rtn, newdir, "getcwd() failed");
189
190   ASSERT_MSG(strcmp(newdir, parent) == 0, "getcwd() failed after chdir");
191   retcode = chdir(dirname);
192   ASSERT_EQ_MSG(retcode, 0, "chdir() failed");
193
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");
197
198   return passed("test_getcwd", "all");
199 }
200
201 bool test_unlink(const char *test_file) {
202   int rtn;
203   struct stat buf;
204   char temp_file[PATH_MAX];
205   snprintf(temp_file, PATH_MAX, "%s.tmp_unlink", test_file);
206   temp_file[PATH_MAX - 1] = '\0';
207
208   int fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
209   ASSERT_MSG(fd >= 0, "open() failed");
210
211   rtn = close(fd);
212   ASSERT_EQ_MSG(rtn, 0, "close() failed");
213
214   rtn = stat(temp_file, &buf);
215   ASSERT_EQ_MSG(rtn, 0, "stat() failed");
216
217   rtn = unlink(temp_file);
218   ASSERT_EQ_MSG(rtn, 0, "unlink() failed");
219
220   rtn = stat(temp_file, &buf);
221   ASSERT_NE_MSG(rtn, 0, "unlink() failed to remove file");
222
223   rtn = unlink(temp_file);
224   ASSERT_NE_MSG(rtn, 0, "unlink() failed to fail");
225
226   return passed("test_unlink", "all");
227 }
228
229 bool test_rename(const char *test_file) {
230   int rtn;
231   struct stat buf;
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);
236
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");
240   rtn = close(fd);
241   ASSERT_EQ_MSG(rtn, 0, "close() failed");
242
243   rtn = stat(filename1, &buf);
244   ASSERT_EQ_MSG(rtn, 0, "stat() failed");
245
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");
250
251   rtn = stat(filename2, &buf);
252   ASSERT_EQ_MSG(rtn, 0, "stat() of new file failed");
253
254   rtn = stat(filename1, &buf);
255   ASSERT_NE_MSG(rtn, 0, "stat() of old name should fail after rename");
256
257   ASSERT_EQ(remove(filename2), 0);
258   return passed("test_rename", "all");
259 }
260
261 bool test_link(const char *test_file) {
262   struct stat buf;
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);
268
269   ensure_file_is_absent(target_filename);
270   ensure_file_is_absent(link_filename);
271
272   // Create link target with some dummy data
273   int fd = open(target_filename, O_WRONLY | O_CREAT, S_IRWXU);
274   ASSERT(fd >= 0);
275   ASSERT_EQ(write(fd, "123", 3), 3);
276   ASSERT_EQ(close(fd), 0);
277
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
281     // to fail.
282     return passed("test_link", "all");
283   }
284   ASSERT_EQ(rtn, 0);
285
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));
292
293   ASSERT_EQ(buf_orig.st_size, 3);
294   ASSERT_EQ(buf_orig.st_size, buf.st_size);
295
296   // Write some bytes to the new file
297   fd = open(link_filename, O_WRONLY);
298   ASSERT(fd >= 0);
299   ASSERT_EQ(write(fd, "test", 4), 4);
300   ASSERT_EQ(close(fd), 0);
301
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);
309
310   ASSERT_EQ(remove(link_filename), 0);
311   ASSERT_EQ(remove(target_filename), 0);
312   return passed("test_link", "all");
313 }
314
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];
319   struct stat buf;
320
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);
324
325   // Split filename into basename and dirname.
326   strncpy(dirname, test_file, PATH_MAX);
327   char *basename = split_name(dirname);
328
329   snprintf(link_filename, PATH_MAX, "%s.link", test_file);
330
331   ensure_file_is_absent(link_filename);
332
333   // Create this link
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");
339   }
340   ASSERT_EQ(rtn, 0);
341
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");
346
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");
350
351   // Test readlink().
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);
359
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);
368
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);
373
374   return passed("test_symlinks", "all");
375 }
376
377 bool test_chmod(const char *test_file) {
378   struct stat buf;
379   char temp_file[PATH_MAX];
380   snprintf(temp_file, PATH_MAX, "%s.tmp_chmod", test_file);
381
382   int fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
383   ASSERT(fd >= 0);
384   ASSERT_EQ(close(fd), 0);
385
386   ASSERT_EQ(stat(temp_file, &buf), 0);
387   ASSERT_EQ(buf.st_mode & ~S_IFMT, S_IRUSR | S_IWUSR);
388
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);
394
395   ASSERT_EQ(remove(temp_file), 0);
396   return passed("test_chmod", "all");
397 }
398
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);
402
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);
406
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);
410
411   /*
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.
415    */
416   // ASSERT_EQ(access(test_file, X_OK), -1);
417   // ASSERT_EQ(access(temp_access, X_OK), -1);
418
419   // Create a read-only file
420   int fd = open(temp_access, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR);
421   ASSERT(fd > 0);
422   ASSERT_EQ(close(fd), 0);
423
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);
428
429   return passed("test_access", "all");
430 }
431
432 bool test_utimes(const char *test_file) {
433   // TODO(mseaborn): Implement utimes for unsandboxed mode.
434   if (NONSFI_MODE)
435     return true;
436   struct timeval times[2];
437   // utimes() is currently not implemented and should always
438   // fail with ENOSYS
439   ASSERT_EQ(utimes("dummy", times), -1);
440   ASSERT_EQ(errno, ENOSYS);
441   return passed("test_utimes", "all");
442 }
443
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);
447
448   char buffer[100];
449   char read_buffer[200];
450   struct stat buf;
451   for (size_t i = 0; i < sizeof(buffer); i++)
452     buffer[i] = i;
453
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);
456   ASSERT(fd >= 0);
457   ASSERT_EQ(100, write(fd, buffer, 100));
458   ASSERT_EQ(0, close(fd));
459
460   ASSERT_EQ(stat(temp_file, &buf), 0);
461   ASSERT_EQ(buf.st_size, 100);
462
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);
467
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);
471   ASSERT(fd >= 0);
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));
477
478   // Now truncate the file to a size smaller than the
479   // original
480   ASSERT_EQ(truncate(temp_file, 50), 0);
481   ASSERT_EQ(stat(temp_file, &buf), 0);
482   ASSERT_EQ(buf.st_size, 50);
483
484   fd = open(temp_file, O_RDONLY);
485   ASSERT(fd >= 0);
486   ASSERT_EQ(read(fd, read_buffer, 50), 50);
487   ASSERT_EQ(memcmp(read_buffer, buffer, 50), 0);
488   ASSERT_EQ(0, close(fd));
489
490   ASSERT_EQ(remove(temp_file), 0);
491   return passed("test_truncate", "all");
492 }
493
494 // open() returns the new file descriptor, or -1 if an error occurred
495 bool test_open(const char *test_file) {
496   int fd;
497   const char *testname = "test_open";
498
499   // file OK, flag OK
500   fd = open(test_file, O_RDONLY);
501   if (fd == -1)
502     return failed(testname, "open(test_file, O_RDONLY)");
503   close(fd);
504
505   errno = 0;
506   // file does not exist, flags OK
507   fd = open("testdata/file_none.txt", O_RDONLY);
508   if (fd != -1)
509     return failed(testname, "open(testdata/file_none.txt, O_RDONLY)");
510   // no such file or directory
511   if (ENOENT != errno)
512     return failed(testname, "ENOENT != errno");
513   close(fd);
514
515   // file OK, flags OK, mode OK
516   fd = open(test_file, O_WRONLY, S_IRUSR);
517   if (fd == -1)
518     return failed(testname, "open(test_file, O_WRONLY, S_IRUSR)");
519   close(fd);
520
521   // too many args
522   fd = open(test_file, O_RDWR, S_IRUSR, O_APPEND);
523   if (fd == -1)
524     return failed(testname, "open(test_file, O_RDWR, S_IRUSR, O_APPEND)");
525   close(fd);
526
527   // directory OK
528   fd = open(".", O_RDONLY);
529   if (fd == -1)
530     return failed(testname, "open(., O_RDONLY)");
531   close(fd);
532
533   errno = 0;
534   // directory does not exist
535   fd = open("nosuchdir", O_RDONLY);
536   if (fd != -1)
537     return failed(testname, "open(nosuchdir, O_RDONLY)");
538   // no such file or directory
539   if (ENOENT != errno)
540     return failed(testname, "ENOENT != errno");
541   close(fd);
542
543   return passed(testname, "all");
544 }
545
546 bool test_stat(const char *test_file) {
547   struct stat buf;
548
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");
553
554   // Test fstat and compare the result with the result of stat.
555   int fd = open(test_file, O_RDONLY);
556   ASSERT_NE(fd, -1);
557   struct stat buf2;
558   int rc = fstat(fd, &buf2);
559   ASSERT_EQ(rc, 0);
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
570   // on Windows.
571   ASSERT_EQ(buf.st_mtime, buf2.st_mtime);
572   ASSERT_EQ(buf.st_ctime, buf2.st_ctime);
573   rc = close(fd);
574   ASSERT_EQ(rc, 0);
575
576   // An invalid fstat call.
577   errno = 0;
578   ASSERT_EQ(fstat(-1, &buf2), -1);
579   ASSERT_EQ(errno, EBADF);
580
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.
585 #if 0
586   char buffer[PATH_MAX];
587   snprintf(buffer, PATH_MAX, "%s.readonly", test_file);
588   buffer[PATH_MAX - 1] = '\0';
589   unlink(buffer);
590   ASSERT_EQ(stat(buffer, &buf), -1);
591   int fd = open(buffer, O_RDWR | O_CREAT, S_IRUSR);
592   ASSERT_NE(fd, -1);
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");
597 #endif
598
599   // Windows doesn't support the concept of write only files,
600   // so we can't test this case.
601
602   return passed("test_stat", "all");
603 }
604
605 // close() returns 0 on success, -1 on error
606 bool test_close(const char *test_file) {
607   int fd;
608   int ret_val;
609   const char *testname = "test_close";
610
611   // file OK
612   fd = open(test_file, O_RDWR);
613   if (fd == -1)
614     return failed(testname, "open(test_file, O_RDWR)");
615   ret_val = close(fd);
616   if (ret_val == -1)
617     return failed(testname, "close(test_file, O_RDWR)");
618
619   // file OK
620   fd = open(test_file, O_RDWR);
621   if (fd == -1)
622     return failed(testname, "open(test_file, O_RDWR)");
623   // close on wrong fd not OK
624   errno = 0;
625   ret_val = close(fd+1);
626   if (ret_val != -1)
627     return failed(testname, "close(fd+1)");
628   // bad file number
629   if (EBADF != errno)
630     return failed(testname, "EBADF != errno");
631   ret_val = close(fd);
632   if (ret_val == -1)
633     return failed(testname, "close(test_file, O_RDWR)");
634
635   // file not OK
636   fd = open("file_none.txt", O_WRONLY);
637   if (fd != -1)
638     return failed(testname, "open(file_none.txt, O_WRONLY)");
639   errno = 0;
640   ret_val = close(fd);
641   if (ret_val == 0)
642     return failed(testname, "close(file_none.txt, O_WRONLY)");
643   // bad file number
644   if (EBADF != errno)
645     return failed(testname, "EBADF != errno");
646
647   // directory OK
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.
650   if (!NONSFI_MODE) {
651     fd = open(".", O_RDWR);
652     if (fd == -1)
653       return failed(testname, "open(., O_RDWR)");
654     ret_val = close(fd);
655     if (ret_val == -1)
656       return failed(testname, "close(., O_RDWR)");
657   }
658
659   // directory not OK
660   fd = open("nosuchdir", O_RDWR);
661   if (fd != -1)
662     return failed(testname, "open(nosuchdir, O_RDWR)");
663   errno = 0;
664   ret_val = close(fd);
665   if (ret_val == 0)
666     return failed(testname, "close(nosuchdir, O_RDWR)");
667   // bad file number
668   if (EBADF != errno)
669     return failed(testname, "EBADF != errno");
670
671   return passed(testname, "all");
672 }
673
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) {
677   int fd;
678   int ret_val;
679   char out_char[5];
680   const char *testname = "test_read";
681
682   fd = open(test_file, O_RDONLY);
683   if (fd == -1)
684     return failed(testname, "open(test_file, O_RDONLY)");
685
686   // fd OK, buffer OK, count OK
687   ret_val = read(fd, out_char, 1);
688   if (ret_val == -1)
689     return failed(testname, "read(fd, out_char, 1)");
690
691   errno = 0;
692   // fd not OK, buffer OK, count OK
693   ret_val = read(-1, out_char, 1);
694   if (ret_val != -1)
695     return failed(testname, "read(-1, out_char, 1)");
696   // bad file number
697   if (EBADF != errno)
698     return failed(testname, "EBADF != errno");
699
700   errno = 0;
701   // fd OK, buffer OK, count not OK
702   // Linux's read() (unsandboxed) does not reject this buffer size.
703   if (!NONSFI_MODE) {
704     ret_val = read(fd, out_char, -1);
705     if (ret_val != -1)
706       return failed(testname, "read(fd, out_char, -1)");
707     // bad address
708     ASSERT_EQ(errno, EFAULT);
709     if (EFAULT != errno)
710       return failed(testname, "EFAULT != errno");
711   }
712
713   errno = 0;
714   // fd not OK, buffer OK, count not OK
715   ret_val = read(-1, out_char, -1);
716   if (ret_val != -1)
717     return failed(testname, "read(-1, out_char, -1)");
718   // bad descriptor
719   if (NONSFI_MODE) {
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");
723   } else {
724     if (EBADF != errno)
725       return failed(testname, "EBADF != errno");
726   }
727
728   // fd OK, buffer OK, count 0
729   ret_val = read(fd, out_char, 0);
730   if (ret_val != 0)
731     return failed(testname, "read(fd, out_char, 0)");
732
733   // read 10, but only 3 are left
734   ret_val = read(fd, out_char, 10);
735   if (ret_val != 4)
736     return failed(testname, "read(fd, out_char, 10)");
737
738   // EOF
739   ret_val = read(fd, out_char, 10);
740   if (ret_val != 0)
741     return failed(testname, "read(fd, out_char, 10)");
742
743   close(fd);
744   return passed(testname, "all");
745 }
746
747 // write() returns the number of bytes written on success, -1 on error
748 bool test_write(const char *test_file) {
749   int fd;
750   int ret_val;
751   char out_char[] = "12";
752   const char *testname = "test_write";
753
754   fd = open(test_file, O_WRONLY);
755   if (fd == -1)
756     return failed(testname, "open(test_file, O_WRONLY)");
757
758   // all params OK
759   ret_val = write(fd, out_char, 2);
760   if (ret_val != 2)
761     return failed(testname, "write(fd, out_char, 2)");
762
763   errno = 0;
764   // invalid count
765   // Linux's write() (unsandboxed) does not reject this buffer size.
766   if (!NONSFI_MODE) {
767     ret_val = write(fd, out_char, -1);
768     if (ret_val != -1)
769       return failed(testname, "write(fd, out_char, -1)");
770     // bad address
771     if (EFAULT != errno)
772       return failed(testname, "EFAULT != errno");
773   }
774
775   errno = 0;
776   // invalid fd
777   ret_val = write(-1, out_char, 2);
778   if (ret_val != -1)
779     return failed(testname, "write(-1, out_char, 2)");
780   // bad address
781   if (EBADF != errno)
782     return failed(testname, "EBADF != errno");
783
784   close(fd);
785   return passed(testname, "all");
786 }
787
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) {
791   int fd;
792   int ret_val;
793   char out_char;
794   const char *testname = "test_lseek";
795
796   fd = open(test_file, O_RDWR);
797   if (fd == -1)
798     return failed(testname, "open(test_file, O_RDWR)");
799
800   ret_val = lseek(fd, 2, SEEK_SET);
801   if (ret_val != 2)
802     return failed(testname, "lseek(fd, 2, SEEK_SET)");
803
804   errno = 0;
805   ret_val = lseek(-1, 1, SEEK_SET);
806   if (ret_val != -1)
807     return failed(testname, "lseek(-1, 1, SEEK_SET)");
808   // bad file number
809   if (EBADF != errno)
810     return failed(testname, "EBADF != errno");
811
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");
815
816   ret_val = lseek(fd, 1, SEEK_CUR);
817   if (ret_val != 4)
818     return failed(testname, "lseek(fd, 1, SEEK_CUR)");
819
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");
823
824   ret_val = lseek(fd, -1, SEEK_CUR);
825   if (ret_val != 4)
826     return failed(testname, "lseek(fd, -1, SEEK_CUR)");
827
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");
831
832   ret_val = lseek(fd, -2, SEEK_END);
833   if (ret_val != 3)
834     return failed(testname, "lseek(fd, -2, SEEK_END)");
835
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");
839
840   ret_val = lseek(fd, 4, SEEK_END);
841   // lseek allows for positioning beyond the EOF
842   if (ret_val != 9)
843     return failed(testname, "lseek(fd, 4, SEEK_END)");
844
845   ret_val = lseek(fd, 4, SEEK_SET);
846   if (ret_val != 4)
847     return failed(testname, "lseek(fd, 4, SEEK_SET)");
848
849   errno = 0;
850   ret_val = lseek(fd, 4, SEEK_END + 3);
851   if (ret_val != -1)
852     return failed(testname, "lseek(fd, 4, SEEK_END + 3)");
853   // invalid argument
854   if (EINVAL != errno)
855     return failed(testname, "EINVAL != errno");
856
857   errno = 0;
858   ret_val = lseek(fd, -40, SEEK_SET);
859   if (ret_val != -1)
860     return failed(testname, "lseek(fd, -40, SEEK_SET)");
861   // invalid argument
862   if (EINVAL != errno)
863     return failed(testname, "EINVAL != errno");
864
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");
868
869   close(fd);
870   return passed(testname, "all");
871 }
872
873 bool test_readdir(const char *test_file) {
874   // TODO(mseaborn): Implement listing directories for unsandboxed mode.
875   if (NONSFI_MODE)
876     return true;
877
878   // Read the directory containing the test file
879
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);
884
885   // Read the directory listing and verify that the test_file is
886   // present.
887   int found = 0;
888   DIR *d = opendir(dirname);
889   ASSERT_NE_MSG(d, NULL, "opendir failed");
890   int count = 0;
891   struct dirent *ent;
892   while (1) {
893     ent = readdir(d);
894     if (!ent)
895       break;
896     if (!strcmp(ent->d_name, basename))
897       found = 1;
898     count++;
899   }
900   ASSERT_EQ_MSG(1, found, "failed to find test file in directory listing");
901
902   // Rewind directory and verify that the number of elements
903   // matches the previous count.
904   rewinddir(d);
905   while (readdir(d))
906     count--;
907   ASSERT_EQ_MSG(0, count, "readdir after rewinddir was inconsistent");
908
909   ASSERT_EQ(0, closedir(d));
910   return passed("test_readdir", "all");
911 }
912
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.
917   if (NONSFI_MODE)
918     if (TESTS_USE_IRT)
919       return true;
920
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__)
925   return true;
926 #endif
927
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");
931   errno = 0;
932   ASSERT_EQ_MSG(isatty(fd), 0, "isatty returned non-zero");
933   ASSERT_EQ_MSG(errno, ENOTTY, "isatty failed to set errno to ENOTTY");
934   close(fd);
935
936   // Verify that isatty() on closed file returns 0 and sets errno to EBADF
937   errno = 0;
938   ASSERT_EQ_MSG(isatty(fd), 0, "isatty returned non-zero");
939   ASSERT_EQ_MSG(errno, EBADF, "isatty failed to set errno to EBADF");
940
941   // On Linux opening /dev/ptmx always returns a TTY file descriptor.
942   fd = open("/dev/ptmx", O_RDWR);
943   if (fd >= 0) {
944     errno = 0;
945     ASSERT_EQ(isatty(fd), 1);
946     ASSERT_EQ(errno, 0);
947     close(fd);
948   }
949
950   return passed("test_isatty", "all");
951 }
952
953 /*
954  * Not strictly speaking a syscall, but we have a 'fake' implementation
955  * that we want to test.
956  */
957 bool test_gethostname() {
958   char hostname[256];
959   ASSERT_EQ(gethostname(hostname, 1), -1);
960 #ifdef __GLIBC__
961   // glibc only provides a stub gethostbyname() that returns
962   // ENOSYS in all cases.
963   ASSERT_EQ(errno, ENOSYS);
964 #else
965   ASSERT_EQ(errno, ENAMETOOLONG);
966
967   errno = 0;
968   ASSERT_EQ(gethostname(hostname, 256), 0);
969   ASSERT_EQ(errno, 0);
970   ASSERT_EQ(strcmp(hostname, "naclhost"), 0);
971 #endif
972   return passed("test_gethostname", "all");
973 }
974
975 /*
976  * function testSuite()
977  *
978  *   Run through a complete sequence of file tests.
979  *
980  * returns true if all tests succeed.  false if one or more fail.
981  */
982
983 bool testSuite(const char *test_file) {
984   bool ret = true;
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);
1007   if (!NONSFI_MODE) {
1008     ret &= test_symlinks(test_file);
1009   }
1010   ret &= test_chmod(test_file);
1011   ret &= test_access(test_file);
1012 #endif
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);
1018 #endif
1019   ret &= test_utimes(test_file);
1020   return ret;
1021 }
1022
1023 /*
1024  * main entry point.
1025  *
1026  * run all tests and call system exit with appropriate value
1027  *   0 - success, all tests passed.
1028  *  -1 - one or more tests failed.
1029  */
1030
1031 int main(const int argc, const char *argv[]) {
1032   bool passed;
1033
1034   if (argc != 2) {
1035     printf("Please specify the test file name\n");
1036     exit(-1);
1037   }
1038   // run the full test suite
1039   passed = testSuite(argv[1]);
1040
1041   if (passed) {
1042     printf("All tests PASSED\n");
1043     exit(0);
1044   } else {
1045     printf("One or more tests FAILED\n");
1046     exit(-1);
1047   }
1048 }