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