1
16
17 package exec
18
19 import (
20 "context"
21 "io"
22 "io/ioutil"
23 "os"
24 osexec "os/exec"
25 "testing"
26 "time"
27 )
28
29 func TestExecutorNoArgs(t *testing.T) {
30 ex := New()
31
32 cmd := ex.Command("true")
33 out, err := cmd.CombinedOutput()
34 if err != nil {
35 t.Errorf("expected success, got %v", err)
36 }
37 if len(out) != 0 {
38 t.Errorf("expected no output, got %q", string(out))
39 }
40
41 cmd = ex.Command("false")
42 out, err = cmd.CombinedOutput()
43 if err == nil {
44 t.Errorf("expected failure, got nil error")
45 }
46 if len(out) != 0 {
47 t.Errorf("expected no output, got %q", string(out))
48 }
49 ee, ok := err.(ExitError)
50 if !ok {
51 t.Errorf("expected an ExitError, got %+v", err)
52 }
53 if ee.Exited() {
54 if code := ee.ExitStatus(); code != 1 {
55 t.Errorf("expected exit status 1, got %d", code)
56 }
57 }
58
59 cmd = ex.Command("/does/not/exist")
60 _, err = cmd.CombinedOutput()
61 if err == nil {
62 t.Errorf("expected failure, got nil error")
63 }
64 if ee, ok := err.(ExitError); ok {
65 t.Errorf("expected non-ExitError, got %+v", ee)
66 }
67 }
68
69 func TestExecutorWithArgs(t *testing.T) {
70 ex := New()
71
72 cmd := ex.Command("echo", "stdout")
73 out, err := cmd.CombinedOutput()
74 if err != nil {
75 t.Errorf("expected success, got %+v", err)
76 }
77 if string(out) != "stdout\n" {
78 t.Errorf("unexpected output: %q", string(out))
79 }
80
81 cmd = ex.Command("/bin/sh", "-c", "echo stderr > /dev/stderr")
82 out, err = cmd.CombinedOutput()
83 if err != nil {
84 t.Errorf("expected success, got %+v", err)
85 }
86 if string(out) != "stderr\n" {
87 t.Errorf("unexpected output: %q", string(out))
88 }
89 }
90
91 func TestLookPath(t *testing.T) {
92 ex := New()
93
94 shExpected, _ := osexec.LookPath("sh")
95 sh, _ := ex.LookPath("sh")
96 if sh != shExpected {
97 t.Errorf("unexpected result for LookPath: got %s, expected %s", sh, shExpected)
98 }
99 }
100
101 func TestExecutableNotFound(t *testing.T) {
102 exec := New()
103
104 cmd := exec.Command("fake_executable_name")
105 _, err := cmd.CombinedOutput()
106 if err != ErrExecutableNotFound {
107 t.Errorf("cmd.CombinedOutput(): Expected error ErrExecutableNotFound but got %v", err)
108 }
109
110 cmd = exec.Command("fake_executable_name")
111 _, err = cmd.Output()
112 if err != ErrExecutableNotFound {
113 t.Errorf("cmd.Output(): Expected error ErrExecutableNotFound but got %v", err)
114 }
115
116 cmd = exec.Command("fake_executable_name")
117 err = cmd.Run()
118 if err != ErrExecutableNotFound {
119 t.Errorf("cmd.Run(): Expected error ErrExecutableNotFound but got %v", err)
120 }
121 }
122
123 func TestStopBeforeStart(t *testing.T) {
124 cmd := New().Command("echo", "hello")
125
126
127 cmd.Stop()
128
129 cmd.Run()
130
131
132 cmd.Stop()
133 }
134
135 func TestTimeout(t *testing.T) {
136 exec := New()
137 ctx, cancel := context.WithTimeout(context.Background(), time.Nanosecond)
138 defer cancel()
139
140 err := exec.CommandContext(ctx, "sleep", "2").Run()
141 if err != context.DeadlineExceeded {
142 t.Errorf("expected %v but got %v", context.DeadlineExceeded, err)
143 }
144 }
145
146 func TestSetEnv(t *testing.T) {
147 ex := New()
148
149 out, err := ex.Command("/bin/sh", "-c", "echo $FOOBAR").CombinedOutput()
150 if err != nil {
151 t.Errorf("expected success, got %+v", err)
152 }
153 if string(out) != "\n" {
154 t.Errorf("unexpected output: %q", string(out))
155 }
156
157 cmd := ex.Command("/bin/sh", "-c", "echo $FOOBAR")
158 cmd.SetEnv([]string{"FOOBAR=baz"})
159 out, err = cmd.CombinedOutput()
160 if err != nil {
161 t.Errorf("expected success, got %+v", err)
162 }
163 if string(out) != "baz\n" {
164 t.Errorf("unexpected output: %q", string(out))
165 }
166 }
167
168 func TestStdIOPipes(t *testing.T) {
169 cmd := New().Command("/bin/sh", "-c", "echo 'OUT'>&1; echo 'ERR'>&2")
170
171 stdoutPipe, err := cmd.StdoutPipe()
172 if err != nil {
173 t.Fatalf("expected StdoutPipe() not to error, got: %v", err)
174 }
175 stderrPipe, err := cmd.StderrPipe()
176 if err != nil {
177 t.Fatalf("expected StderrPipe() not to error, got: %v", err)
178 }
179
180 stdout := make(chan string)
181 stderr := make(chan string)
182
183 go func() {
184 stdout <- readAll(t, stdoutPipe, "StdOut")
185 }()
186 go func() {
187 stderr <- readAll(t, stderrPipe, "StdErr")
188 }()
189
190 if err := cmd.Start(); err != nil {
191 t.Errorf("expected Start() not to error, got: %v", err)
192 }
193
194 if e, a := "OUT\n", <-stdout; e != a {
195 t.Errorf("expected StdOut to be '%s', got: '%v'", e, a)
196 }
197
198 if e, a := "ERR\n", <-stderr; e != a {
199 t.Errorf("expected StdErr to be '%s', got: '%v'", e, a)
200 }
201
202 if err := cmd.Wait(); err != nil {
203 t.Errorf("expected Wait() not to error, got: %v", err)
204 }
205 }
206
207 func readAll(t *testing.T, r io.Reader, n string) string {
208 t.Helper()
209
210 b, err := ioutil.ReadAll(r)
211 if err != nil {
212 t.Fatalf("unexpected error when reading from %s: %v", n, err)
213 }
214
215 return string(b)
216 }
217
218 func TestExecutorGo119LookPath(t *testing.T) {
219 orig := os.Getenv("PATH")
220 defer func() { os.Setenv("PATH", orig) }()
221
222 os.Setenv("PATH", "./testdata")
223
224 ex := New()
225 path, err := ex.LookPath("hello")
226 if err != nil {
227 t.Errorf("expected success, got %v", err)
228 }
229 if path != "testdata/hello" {
230 t.Errorf("expected relative path to hello script, got %v", path)
231 }
232
233 cmd := ex.Command("hello")
234 out, err := cmd.CombinedOutput()
235 if err != nil {
236 t.Errorf("expected success, got %v", err)
237 } else {
238 if len(out) != 5 {
239 t.Errorf("expected 'hello' output, got %q", string(out))
240 }
241 }
242
243 cmd = ex.CommandContext(context.Background(), "hello")
244 out, err = cmd.CombinedOutput()
245 if err != nil {
246 t.Errorf("expected success, got %v", err)
247 } else {
248 if len(out) != 5 {
249 t.Errorf("expected 'hello' output, got %q", string(out))
250 }
251 }
252 }
253
View as plain text