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.
17 const executable_EnvVar
= "OSTEST_OUTPUT_EXECPATH"
19 func TestExecutable(t
*testing
.T
) {
20 testenv
.MustHaveExec(t
)
21 ep
, err
:= os
.Executable()
23 t
.Fatalf("Executable failed: %v", err
)
25 // we want fn to be of the form "dir/prog"
26 dir
:= filepath
.Dir(filepath
.Dir(ep
))
27 fn
, err
:= filepath
.Rel(dir
, ep
)
29 t
.Fatalf("filepath.Rel: %v", err
)
33 // make child start with a relative program path
36 // forge argv[0] for child, so that we can verify we could correctly
37 // get real path of the executable without influenced by argv[0].
38 cmd
.Args
= []string{"-", "-test.run=XXXX"}
39 if runtime
.GOOS
== "openbsd" || runtime
.GOOS
== "aix" {
40 // OpenBSD and AIX rely on argv[0]
43 cmd
.Env
= append(os
.Environ(), fmt
.Sprintf("%s=1", executable_EnvVar
))
44 out
, err
:= cmd
.CombinedOutput()
46 t
.Fatalf("exec(self) failed: %v", err
)
49 if !filepath
.IsAbs(outs
) {
50 t
.Fatalf("Child returned %q, want an absolute path", out
)
52 if !sameFile(outs
, ep
) {
53 t
.Fatalf("Child returned %q, not the same file as %q", out
, ep
)
57 func sameFile(fn1
, fn2
string) bool {
58 fi1
, err
:= os
.Stat(fn1
)
62 fi2
, err
:= os
.Stat(fn2
)
66 return os
.SameFile(fi1
, fi2
)
70 if e
:= os
.Getenv(executable_EnvVar
); e
!= "" {
71 // first chdir to another path
73 if runtime
.GOOS
== "windows" {
74 cwd
, err
:= os
.Getwd()
78 dir
= filepath
.VolumeName(cwd
)
81 if ep
, err
:= os
.Executable(); err
!= nil {
82 fmt
.Fprint(os
.Stderr
, "ERROR: ", err
)
84 fmt
.Fprint(os
.Stderr
, ep
)
90 func TestExecutableDeleted(t
*testing
.T
) {
91 testenv
.MustHaveExec(t
)
93 case "windows", "plan9":
94 t
.Skipf("%v does not support deleting running binary", runtime
.GOOS
)
95 case "openbsd", "freebsd", "aix":
96 t
.Skipf("%v does not support reading deleted binary name", runtime
.GOOS
)
101 src
:= filepath
.Join(dir
, "testdel.go")
102 exe
:= filepath
.Join(dir
, "testdel.exe")
104 err
:= os
.WriteFile(src
, []byte(testExecutableDeletion
), 0666)
109 out
, err
:= osexec
.Command(testenv
.GoToolPath(t
), "build", "-o", exe
, src
).CombinedOutput()
110 t
.Logf("build output:\n%s", out
)
115 out
, err
= osexec
.Command(exe
).CombinedOutput()
116 t
.Logf("exec output:\n%s", out
)
122 const testExecutableDeletion
= `package main
130 before, err := os.Executable()
132 fmt.Fprintf(os.Stderr, "failed to read executable name before deletion: %v\n", err)
136 err = os.Remove(before)
138 fmt.Fprintf(os.Stderr, "failed to remove executable: %v\n", err)
142 after, err := os.Executable()
144 fmt.Fprintf(os.Stderr, "failed to read executable name after deletion: %v\n", err)
149 fmt.Fprintf(os.Stderr, "before and after do not match: %v != %v\n", before, after)