github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/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 }