github.com/activestate/go@v0.0.0-20170614201249-0b81c023a722/src/os/executable_test.go (about)

     1  // Copyright 2016 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  package os_test
     6  
     7  import (
     8  	"fmt"
     9  	"internal/testenv"
    10  	"os"
    11  	osexec "os/exec"
    12  	"path/filepath"
    13  	"runtime"
    14  	"testing"
    15  )
    16  
    17  const executable_EnvVar = "OSTEST_OUTPUT_EXECPATH"
    18  
    19  func TestExecutable(t *testing.T) {
    20  	testenv.MustHaveExec(t) // will also execlude nacl, which doesn't support Executable anyway
    21  	ep, err := os.Executable()
    22  	if err != nil {
    23  		switch goos := runtime.GOOS; goos {
    24  		case "openbsd": // procfs is not mounted by default
    25  			t.Skipf("Executable failed on %s: %v, expected", goos, err)
    26  		}
    27  		t.Fatalf("Executable failed: %v", err)
    28  	}
    29  	// we want fn to be of the form "dir/prog"
    30  	dir := filepath.Dir(filepath.Dir(ep))
    31  	fn, err := filepath.Rel(dir, ep)
    32  	if err != nil {
    33  		t.Fatalf("filepath.Rel: %v", err)
    34  	}
    35  	cmd := &osexec.Cmd{}
    36  	// make child start with a relative program path
    37  	cmd.Dir = dir
    38  	cmd.Path = fn
    39  	// forge argv[0] for child, so that we can verify we could correctly
    40  	// get real path of the executable without influenced by argv[0].
    41  	cmd.Args = []string{"-", "-test.run=XXXX"}
    42  	cmd.Env = append(os.Environ(), fmt.Sprintf("%s=1", executable_EnvVar))
    43  	out, err := cmd.CombinedOutput()
    44  	if err != nil {
    45  		t.Fatalf("exec(self) failed: %v", err)
    46  	}
    47  	outs := string(out)
    48  	if !filepath.IsAbs(outs) {
    49  		t.Fatalf("Child returned %q, want an absolute path", out)
    50  	}
    51  	if !sameFile(outs, ep) {
    52  		t.Fatalf("Child returned %q, not the same file as %q", out, ep)
    53  	}
    54  }
    55  
    56  func sameFile(fn1, fn2 string) bool {
    57  	fi1, err := os.Stat(fn1)
    58  	if err != nil {
    59  		return false
    60  	}
    61  	fi2, err := os.Stat(fn2)
    62  	if err != nil {
    63  		return false
    64  	}
    65  	return os.SameFile(fi1, fi2)
    66  }
    67  
    68  func init() {
    69  	if e := os.Getenv(executable_EnvVar); e != "" {
    70  		// first chdir to another path
    71  		dir := "/"
    72  		if runtime.GOOS == "windows" {
    73  			cwd, err := os.Getwd()
    74  			if err != nil {
    75  				panic(err)
    76  			}
    77  			dir = filepath.VolumeName(cwd)
    78  		}
    79  		os.Chdir(dir)
    80  		if ep, err := os.Executable(); err != nil {
    81  			fmt.Fprint(os.Stderr, "ERROR: ", err)
    82  		} else {
    83  			fmt.Fprint(os.Stderr, ep)
    84  		}
    85  		os.Exit(0)
    86  	}
    87  }