darwin_test.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Copyright 2018 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build darwin,go1.12,amd64 darwin,go1.12,386
  5. package unix
  6. import (
  7. "os"
  8. "os/exec"
  9. "strings"
  10. "testing"
  11. )
  12. type darwinTest struct {
  13. name string
  14. f func()
  15. }
  16. // TODO(khr): decide whether to keep this test enabled permanently or
  17. // only temporarily.
  18. func TestDarwinLoader(t *testing.T) {
  19. // Make sure the Darwin dynamic loader can actually resolve
  20. // all the system calls into libSystem.dylib. Unfortunately
  21. // there is no easy way to test this at compile time. So we
  22. // implement a crazy hack here, calling into the syscall
  23. // function with all its arguments set to junk, and see what
  24. // error we get. We are happy with any error (or none) except
  25. // an error from the dynamic loader.
  26. //
  27. // We have to run each test in a separate subprocess for fault isolation.
  28. //
  29. // Hopefully the junk args won't accidentally ask the system to do "rm -fr /".
  30. //
  31. // In an ideal world each syscall would have its own test, so this test
  32. // would be unnecessary. Unfortunately, we do not live in that world.
  33. for _, test := range darwinTests {
  34. // Call the test binary recursively, giving it a magic argument
  35. // (see init below) and the name of the test to run.
  36. cmd := exec.Command(os.Args[0], "testDarwinLoader", test.name)
  37. // Run subprocess, collect results. Note that we expect the subprocess
  38. // to fail somehow, so the error is irrelevant.
  39. out, _ := cmd.CombinedOutput()
  40. if strings.Contains(string(out), "dyld: Symbol not found:") {
  41. t.Errorf("can't resolve %s in libSystem.dylib", test.name)
  42. }
  43. if !strings.Contains(string(out), "success") {
  44. // Not really an error. Might be a syscall that never returns,
  45. // like exit, or one that segfaults, like gettimeofday.
  46. t.Logf("test never finished: %s: %s", test.name, string(out))
  47. }
  48. }
  49. }
  50. func init() {
  51. // The test binary execs itself with the "testDarwinLoader" argument.
  52. // Run the test specified by os.Args[2], then panic.
  53. if len(os.Args) >= 3 && os.Args[1] == "testDarwinLoader" {
  54. for _, test := range darwinTests {
  55. if test.name == os.Args[2] {
  56. test.f()
  57. }
  58. }
  59. // Panic with a "success" label, so the parent process can check it.
  60. panic("success")
  61. }
  62. }
  63. // All the _trampoline functions in zsyscall_darwin_$ARCH.s
  64. var darwinTests = [...]darwinTest{
  65. {"getgroups", libc_getgroups_trampoline},
  66. {"setgroups", libc_setgroups_trampoline},
  67. {"wait4", libc_wait4_trampoline},
  68. {"accept", libc_accept_trampoline},
  69. {"bind", libc_bind_trampoline},
  70. {"connect", libc_connect_trampoline},
  71. {"socket", libc_socket_trampoline},
  72. {"getsockopt", libc_getsockopt_trampoline},
  73. {"setsockopt", libc_setsockopt_trampoline},
  74. {"getpeername", libc_getpeername_trampoline},
  75. {"getsockname", libc_getsockname_trampoline},
  76. {"shutdown", libc_shutdown_trampoline},
  77. {"socketpair", libc_socketpair_trampoline},
  78. {"recvfrom", libc_recvfrom_trampoline},
  79. {"sendto", libc_sendto_trampoline},
  80. {"recvmsg", libc_recvmsg_trampoline},
  81. {"sendmsg", libc_sendmsg_trampoline},
  82. {"kevent", libc_kevent_trampoline},
  83. {"__sysctl", libc___sysctl_trampoline},
  84. {"utimes", libc_utimes_trampoline},
  85. {"futimes", libc_futimes_trampoline},
  86. {"fcntl", libc_fcntl_trampoline},
  87. {"poll", libc_poll_trampoline},
  88. {"madvise", libc_madvise_trampoline},
  89. {"mlock", libc_mlock_trampoline},
  90. {"mlockall", libc_mlockall_trampoline},
  91. {"mprotect", libc_mprotect_trampoline},
  92. {"msync", libc_msync_trampoline},
  93. {"munlock", libc_munlock_trampoline},
  94. {"munlockall", libc_munlockall_trampoline},
  95. {"ptrace", libc_ptrace_trampoline},
  96. {"pipe", libc_pipe_trampoline},
  97. {"getxattr", libc_getxattr_trampoline},
  98. {"fgetxattr", libc_fgetxattr_trampoline},
  99. {"setxattr", libc_setxattr_trampoline},
  100. {"fsetxattr", libc_fsetxattr_trampoline},
  101. {"removexattr", libc_removexattr_trampoline},
  102. {"fremovexattr", libc_fremovexattr_trampoline},
  103. {"listxattr", libc_listxattr_trampoline},
  104. {"flistxattr", libc_flistxattr_trampoline},
  105. {"kill", libc_kill_trampoline},
  106. {"ioctl", libc_ioctl_trampoline},
  107. {"access", libc_access_trampoline},
  108. {"adjtime", libc_adjtime_trampoline},
  109. {"chdir", libc_chdir_trampoline},
  110. {"chflags", libc_chflags_trampoline},
  111. {"chmod", libc_chmod_trampoline},
  112. {"chown", libc_chown_trampoline},
  113. {"chroot", libc_chroot_trampoline},
  114. {"close", libc_close_trampoline},
  115. {"dup", libc_dup_trampoline},
  116. {"dup2", libc_dup2_trampoline},
  117. {"exchangedata", libc_exchangedata_trampoline},
  118. {"exit", libc_exit_trampoline},
  119. {"faccessat", libc_faccessat_trampoline},
  120. {"fchdir", libc_fchdir_trampoline},
  121. {"fchflags", libc_fchflags_trampoline},
  122. {"fchmod", libc_fchmod_trampoline},
  123. {"fchmodat", libc_fchmodat_trampoline},
  124. {"fchown", libc_fchown_trampoline},
  125. {"fchownat", libc_fchownat_trampoline},
  126. {"flock", libc_flock_trampoline},
  127. {"fpathconf", libc_fpathconf_trampoline},
  128. {"fstat64", libc_fstat64_trampoline},
  129. {"fstatat64", libc_fstatat64_trampoline},
  130. {"fstatfs64", libc_fstatfs64_trampoline},
  131. {"fsync", libc_fsync_trampoline},
  132. {"ftruncate", libc_ftruncate_trampoline},
  133. {"getdtablesize", libc_getdtablesize_trampoline},
  134. {"getegid", libc_getegid_trampoline},
  135. {"geteuid", libc_geteuid_trampoline},
  136. {"getgid", libc_getgid_trampoline},
  137. {"getpgid", libc_getpgid_trampoline},
  138. {"getpgrp", libc_getpgrp_trampoline},
  139. {"getpid", libc_getpid_trampoline},
  140. {"getppid", libc_getppid_trampoline},
  141. {"getpriority", libc_getpriority_trampoline},
  142. {"getrlimit", libc_getrlimit_trampoline},
  143. {"getrusage", libc_getrusage_trampoline},
  144. {"getsid", libc_getsid_trampoline},
  145. {"getuid", libc_getuid_trampoline},
  146. {"issetugid", libc_issetugid_trampoline},
  147. {"kqueue", libc_kqueue_trampoline},
  148. {"lchown", libc_lchown_trampoline},
  149. {"link", libc_link_trampoline},
  150. {"linkat", libc_linkat_trampoline},
  151. {"listen", libc_listen_trampoline},
  152. {"lstat64", libc_lstat64_trampoline},
  153. {"mkdir", libc_mkdir_trampoline},
  154. {"mkdirat", libc_mkdirat_trampoline},
  155. {"mkfifo", libc_mkfifo_trampoline},
  156. {"mknod", libc_mknod_trampoline},
  157. {"open", libc_open_trampoline},
  158. {"openat", libc_openat_trampoline},
  159. {"pathconf", libc_pathconf_trampoline},
  160. {"pread", libc_pread_trampoline},
  161. {"pwrite", libc_pwrite_trampoline},
  162. {"read", libc_read_trampoline},
  163. {"readlink", libc_readlink_trampoline},
  164. {"readlinkat", libc_readlinkat_trampoline},
  165. {"rename", libc_rename_trampoline},
  166. {"renameat", libc_renameat_trampoline},
  167. {"revoke", libc_revoke_trampoline},
  168. {"rmdir", libc_rmdir_trampoline},
  169. {"lseek", libc_lseek_trampoline},
  170. {"select", libc_select_trampoline},
  171. {"setegid", libc_setegid_trampoline},
  172. {"seteuid", libc_seteuid_trampoline},
  173. {"setgid", libc_setgid_trampoline},
  174. {"setlogin", libc_setlogin_trampoline},
  175. {"setpgid", libc_setpgid_trampoline},
  176. {"setpriority", libc_setpriority_trampoline},
  177. {"setprivexec", libc_setprivexec_trampoline},
  178. {"setregid", libc_setregid_trampoline},
  179. {"setreuid", libc_setreuid_trampoline},
  180. {"setrlimit", libc_setrlimit_trampoline},
  181. {"setsid", libc_setsid_trampoline},
  182. {"settimeofday", libc_settimeofday_trampoline},
  183. {"setuid", libc_setuid_trampoline},
  184. {"stat64", libc_stat64_trampoline},
  185. {"statfs64", libc_statfs64_trampoline},
  186. {"symlink", libc_symlink_trampoline},
  187. {"symlinkat", libc_symlinkat_trampoline},
  188. {"sync", libc_sync_trampoline},
  189. {"truncate", libc_truncate_trampoline},
  190. {"umask", libc_umask_trampoline},
  191. {"undelete", libc_undelete_trampoline},
  192. {"unlink", libc_unlink_trampoline},
  193. {"unlinkat", libc_unlinkat_trampoline},
  194. {"unmount", libc_unmount_trampoline},
  195. {"write", libc_write_trampoline},
  196. {"mmap", libc_mmap_trampoline},
  197. {"munmap", libc_munmap_trampoline},
  198. {"gettimeofday", libc_gettimeofday_trampoline},
  199. {"getfsstat64", libc_getfsstat64_trampoline},
  200. }