1
2
3
4
5 package execabs
6
7 import (
8 "context"
9 "fmt"
10 "os"
11 "os/exec"
12 "path/filepath"
13 "runtime"
14 "strings"
15 "testing"
16 )
17
18
19
20
21 func hasExec() bool {
22 switch runtime.GOOS {
23 case "wasip1", "js", "ios":
24 return false
25 }
26 return true
27 }
28
29
30
31
32
33 func mustHaveExec(t testing.TB) {
34 if !hasExec() {
35 t.Skipf("skipping test: cannot exec subprocess on %s/%s", runtime.GOOS, runtime.GOARCH)
36 }
37 }
38
39 func TestFixCmd(t *testing.T) {
40 cmd := &exec.Cmd{Path: "hello"}
41 fixCmd("hello", cmd)
42 if cmd.Path != "" {
43 t.Errorf("fixCmd didn't clear cmd.Path")
44 }
45 expectedErr := fmt.Sprintf("hello resolves to executable in current directory (.%chello)", filepath.Separator)
46 if err := cmd.Run(); err == nil {
47 t.Fatal("Command.Run didn't fail")
48 } else if err.Error() != expectedErr {
49 t.Fatalf("Command.Run returned unexpected error: want %q, got %q", expectedErr, err.Error())
50 }
51 }
52
53 func TestCommand(t *testing.T) {
54 mustHaveExec(t)
55
56 for _, cmd := range []func(string) *Cmd{
57 func(s string) *Cmd { return Command(s) },
58 func(s string) *Cmd { return CommandContext(context.Background(), s) },
59 } {
60 tmpDir := t.TempDir()
61 executable := "execabs-test"
62 if runtime.GOOS == "windows" {
63 executable += ".exe"
64 }
65 if err := os.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
66 t.Fatal(err)
67 }
68 cwd, err := os.Getwd()
69 if err != nil {
70 t.Fatalf("os.Getwd failed: %s", err)
71 }
72 defer os.Chdir(cwd)
73 if err = os.Chdir(tmpDir); err != nil {
74 t.Fatalf("os.Chdir failed: %s", err)
75 }
76 if runtime.GOOS != "windows" {
77
78
79 origPath := os.Getenv("PATH")
80 defer os.Setenv("PATH", origPath)
81 os.Setenv("PATH", fmt.Sprintf(".:%s", origPath))
82 }
83 expectedErr := fmt.Sprintf("execabs-test resolves to executable in current directory (.%c%s)", filepath.Separator, executable)
84 if err = cmd("execabs-test").Run(); err == nil {
85 t.Fatalf("Command.Run didn't fail when exec.LookPath returned a relative path")
86 } else if err.Error() != expectedErr && !isGo119ErrDot(err) {
87 t.Errorf("Command.Run returned unexpected error: want %q, got %q", expectedErr, err.Error())
88 }
89 }
90 }
91
92 func TestLookPath(t *testing.T) {
93 mustHaveExec(t)
94
95 tmpDir := t.TempDir()
96 executable := "execabs-test"
97 if runtime.GOOS == "windows" {
98 executable += ".exe"
99 }
100 if err := os.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
101 t.Fatal(err)
102 }
103 cwd, err := os.Getwd()
104 if err != nil {
105 t.Fatalf("os.Getwd failed: %s", err)
106 }
107 defer os.Chdir(cwd)
108 if err = os.Chdir(tmpDir); err != nil {
109 t.Fatalf("os.Chdir failed: %s", err)
110 }
111 if runtime.GOOS != "windows" {
112
113
114 origPath := os.Getenv("PATH")
115 defer os.Setenv("PATH", origPath)
116 os.Setenv("PATH", fmt.Sprintf(".:%s", origPath))
117 }
118 expectedErr := fmt.Sprintf("execabs-test resolves to executable in current directory (.%c%s)", filepath.Separator, executable)
119 if _, err := LookPath("execabs-test"); err == nil {
120 t.Fatalf("LookPath didn't fail when finding a non-relative path")
121 } else if err.Error() != expectedErr {
122 t.Errorf("LookPath returned unexpected error: want %q, got %q", expectedErr, err.Error())
123 }
124 }
125
126
127 func TestDoesNotExist(t *testing.T) {
128 err := Command("this-executable-should-not-exist").Start()
129 if err == nil {
130 t.Fatal("command should have failed")
131 }
132 if strings.Contains(err.Error(), "resolves to executable in current directory") {
133 t.Errorf("error (%v) should not refer to current directory", err)
134 }
135 }
136
View as plain text