go4.org@v0.0.0-20230225012048-214862532bf5/osutil/exec_test.go (about) 1 // Copyright 2015 The go4 Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package osutil 16 17 import ( 18 "fmt" 19 "os" 20 osexec "os/exec" 21 "path/filepath" 22 "runtime" 23 "testing" 24 ) 25 26 const executable_EnvVar = "OSTEST_OUTPUT_EXECPATH" 27 28 func TestExecutable(t *testing.T) { 29 if runtime.GOOS == "nacl" { 30 t.Skip() 31 } 32 ep, err := Executable() 33 if err != nil { 34 switch goos := runtime.GOOS; goos { 35 case "openbsd": // procfs is not mounted by default 36 t.Skipf("Executable failed on %s: %v, expected", goos, err) 37 } 38 t.Fatalf("Executable failed: %v", err) 39 } 40 // we want fn to be of the form "dir/prog" 41 dir := filepath.Dir(filepath.Dir(ep)) 42 fn, err := filepath.Rel(dir, ep) 43 if err != nil { 44 t.Fatalf("filepath.Rel: %v", err) 45 } 46 cmd := &osexec.Cmd{} 47 // make child start with a relative program path 48 cmd.Dir = dir 49 cmd.Path = fn 50 // forge argv[0] for child, so that we can verify we could correctly 51 // get real path of the executable without influenced by argv[0]. 52 cmd.Args = []string{"-", "-test.run=XXXX"} 53 cmd.Env = []string{fmt.Sprintf("%s=1", executable_EnvVar)} 54 out, err := cmd.CombinedOutput() 55 if err != nil { 56 t.Fatalf("exec(self) failed: %v", err) 57 } 58 outs := string(out) 59 if !filepath.IsAbs(outs) { 60 t.Fatalf("Child returned %q, want an absolute path", out) 61 } 62 if !sameFile(outs, ep) { 63 t.Fatalf("Child returned %q, not the same file as %q", out, ep) 64 } 65 } 66 67 func sameFile(fn1, fn2 string) bool { 68 fi1, err := os.Stat(fn1) 69 if err != nil { 70 return false 71 } 72 fi2, err := os.Stat(fn2) 73 if err != nil { 74 return false 75 } 76 return os.SameFile(fi1, fi2) 77 } 78 79 func init() { 80 if e := os.Getenv(executable_EnvVar); e != "" { 81 // first chdir to another path 82 dir := "/" 83 if runtime.GOOS == "windows" { 84 dir = filepath.VolumeName(".") 85 } 86 os.Chdir(dir) 87 if ep, err := Executable(); err != nil { 88 fmt.Fprint(os.Stderr, "ERROR: ", err) 89 } else { 90 fmt.Fprint(os.Stderr, ep) 91 } 92 os.Exit(0) 93 } 94 }