golang.org/x/sys@v0.9.0/unix/darwin_test.go (about) 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 5 //go:build darwin && go1.12 6 // +build darwin,go1.12 7 8 package unix 9 10 import ( 11 "os" 12 "os/exec" 13 "strings" 14 "testing" 15 ) 16 17 type darwinTest struct { 18 name string 19 f uintptr 20 } 21 22 // TODO(khr): decide whether to keep this test enabled permanently or 23 // only temporarily. 24 func TestDarwinLoader(t *testing.T) { 25 // Make sure the Darwin dynamic loader can actually resolve 26 // all the system calls into libSystem.dylib. Unfortunately 27 // there is no easy way to test this at compile time. So we 28 // implement a crazy hack here, calling into the syscall 29 // function with all its arguments set to junk, and see what 30 // error we get. We are happy with any error (or none) except 31 // an error from the dynamic loader. 32 // 33 // We have to run each test in a separate subprocess for fault isolation. 34 // 35 // Hopefully the junk args won't accidentally ask the system to do "rm -fr /". 36 // 37 // In an ideal world each syscall would have its own test, so this test 38 // would be unnecessary. Unfortunately, we do not live in that world. 39 for _, test := range darwinTests { 40 // Call the test binary recursively, giving it a magic argument 41 // (see init below) and the name of the test to run. 42 cmd := exec.Command(os.Args[0], "testDarwinLoader", test.name) 43 44 // Run subprocess, collect results. Note that we expect the subprocess 45 // to fail somehow, so the error is irrelevant. 46 out, _ := cmd.CombinedOutput() 47 48 if strings.Contains(string(out), "dyld: Symbol not found:") { 49 t.Errorf("can't resolve %s in libSystem.dylib", test.name) 50 } 51 if !strings.Contains(string(out), "success") { 52 // Not really an error. Might be a syscall that never returns, 53 // like exit, or one that segfaults, like gettimeofday. 54 t.Logf("test never finished: %s: %s", test.name, string(out)) 55 } 56 } 57 } 58 59 func init() { 60 // The test binary execs itself with the "testDarwinLoader" argument. 61 // Run the test specified by os.Args[2], then panic. 62 if len(os.Args) >= 3 && os.Args[1] == "testDarwinLoader" { 63 for _, test := range darwinTests { 64 if test.name == os.Args[2] { 65 syscall_syscall(test.f, ^uintptr(0), ^uintptr(0), ^uintptr(0)) 66 } 67 } 68 // Panic with a "success" label, so the parent process can check it. 69 panic("success") 70 } 71 }