github.com/kakami/go-update@v0.0.0-20160112193335-8152e7eb6ccf/internal/osext/osext_test.go (about) 1 // Copyright 2012 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 // +build darwin linux freebsd netbsd windows 6 7 package osext 8 9 import ( 10 "bytes" 11 "fmt" 12 "io" 13 "os" 14 "os/exec" 15 "path/filepath" 16 "runtime" 17 "testing" 18 ) 19 20 const ( 21 executableEnvVar = "OSTEST_OUTPUT_EXECUTABLE" 22 23 executableEnvValueMatch = "match" 24 executableEnvValueDelete = "delete" 25 ) 26 27 func TestPrintExecutable(t *testing.T) { 28 ef, err := Executable() 29 if err != nil { 30 t.Fatalf("Executable failed: %v", err) 31 } 32 t.Log("Executable:", ef) 33 } 34 func TestPrintExecutableFolder(t *testing.T) { 35 ef, err := ExecutableFolder() 36 if err != nil { 37 t.Fatalf("ExecutableFolder failed: %v", err) 38 } 39 t.Log("Executable Folder:", ef) 40 } 41 func TestExecutableFolder(t *testing.T) { 42 ef, err := ExecutableFolder() 43 if err != nil { 44 t.Fatalf("ExecutableFolder failed: %v", err) 45 } 46 if ef[len(ef)-1] == filepath.Separator { 47 t.Fatal("ExecutableFolder ends with a trailing slash.") 48 } 49 } 50 func TestExecutableMatch(t *testing.T) { 51 ep, err := Executable() 52 if err != nil { 53 t.Fatalf("Executable failed: %v", err) 54 } 55 56 // fullpath to be of the form "dir/prog". 57 dir := filepath.Dir(filepath.Dir(ep)) 58 fullpath, err := filepath.Rel(dir, ep) 59 if err != nil { 60 t.Fatalf("filepath.Rel: %v", err) 61 } 62 // Make child start with a relative program path. 63 // Alter argv[0] for child to verify getting real path without argv[0]. 64 cmd := &exec.Cmd{ 65 Dir: dir, 66 Path: fullpath, 67 Env: []string{fmt.Sprintf("%s=%s", executableEnvVar, executableEnvValueMatch)}, 68 } 69 out, err := cmd.CombinedOutput() 70 if err != nil { 71 t.Fatalf("exec(self) failed: %v", err) 72 } 73 outs := string(out) 74 if !filepath.IsAbs(outs) { 75 t.Fatalf("Child returned %q, want an absolute path", out) 76 } 77 if !sameFile(outs, ep) { 78 t.Fatalf("Child returned %q, not the same file as %q", out, ep) 79 } 80 } 81 82 func TestExecutableDelete(t *testing.T) { 83 if runtime.GOOS != "linux" { 84 t.Skip() 85 } 86 fpath, err := Executable() 87 if err != nil { 88 t.Fatalf("Executable failed: %v", err) 89 } 90 91 r, w := io.Pipe() 92 stderrBuff := &bytes.Buffer{} 93 stdoutBuff := &bytes.Buffer{} 94 cmd := &exec.Cmd{ 95 Path: fpath, 96 Env: []string{fmt.Sprintf("%s=%s", executableEnvVar, executableEnvValueDelete)}, 97 Stdin: r, 98 Stderr: stderrBuff, 99 Stdout: stdoutBuff, 100 } 101 err = cmd.Start() 102 if err != nil { 103 t.Fatalf("exec(self) start failed: %v", err) 104 } 105 106 tempPath := fpath + "_copy" 107 _ = os.Remove(tempPath) 108 109 err = copyFile(tempPath, fpath) 110 if err != nil { 111 t.Fatalf("copy file failed: %v", err) 112 } 113 err = os.Remove(fpath) 114 if err != nil { 115 t.Fatalf("remove running test file failed: %v", err) 116 } 117 err = os.Rename(tempPath, fpath) 118 if err != nil { 119 t.Fatalf("rename copy to previous name failed: %v", err) 120 } 121 122 w.Write([]byte{0}) 123 w.Close() 124 125 err = cmd.Wait() 126 if err != nil { 127 t.Fatalf("exec wait failed: %v", err) 128 } 129 130 childPath := stderrBuff.String() 131 if !filepath.IsAbs(childPath) { 132 t.Fatalf("Child returned %q, want an absolute path", childPath) 133 } 134 if !sameFile(childPath, fpath) { 135 t.Fatalf("Child returned %q, not the same file as %q", childPath, fpath) 136 } 137 } 138 139 func sameFile(fn1, fn2 string) bool { 140 fi1, err := os.Stat(fn1) 141 if err != nil { 142 return false 143 } 144 fi2, err := os.Stat(fn2) 145 if err != nil { 146 return false 147 } 148 return os.SameFile(fi1, fi2) 149 } 150 func copyFile(dest, src string) error { 151 df, err := os.Create(dest) 152 if err != nil { 153 return err 154 } 155 defer df.Close() 156 157 sf, err := os.Open(src) 158 if err != nil { 159 return err 160 } 161 defer sf.Close() 162 163 _, err = io.Copy(df, sf) 164 return err 165 } 166 167 func TestMain(m *testing.M) { 168 env := os.Getenv(executableEnvVar) 169 switch env { 170 case "": 171 os.Exit(m.Run()) 172 case executableEnvValueMatch: 173 // First chdir to another path. 174 dir := "/" 175 if runtime.GOOS == "windows" { 176 dir = filepath.VolumeName(".") 177 } 178 os.Chdir(dir) 179 if ep, err := Executable(); err != nil { 180 fmt.Fprint(os.Stderr, "ERROR: ", err) 181 } else { 182 fmt.Fprint(os.Stderr, ep) 183 } 184 case executableEnvValueDelete: 185 bb := make([]byte, 1) 186 var err error 187 n, err := os.Stdin.Read(bb) 188 if err != nil { 189 fmt.Fprint(os.Stderr, "ERROR: ", err) 190 os.Exit(2) 191 } 192 if n != 1 { 193 fmt.Fprint(os.Stderr, "ERROR: n != 1, n == ", n) 194 os.Exit(2) 195 } 196 if ep, err := Executable(); err != nil { 197 fmt.Fprint(os.Stderr, "ERROR: ", err) 198 } else { 199 fmt.Fprint(os.Stderr, ep) 200 } 201 } 202 os.Exit(0) 203 }