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  }