1 package icmd
2
3 import (
4 "bytes"
5 "errors"
6 "os"
7 "os/exec"
8 "path/filepath"
9 "runtime"
10 "testing"
11 "time"
12
13 "gotest.tools/v3/assert"
14 "gotest.tools/v3/fs"
15 "gotest.tools/v3/internal/maint"
16 )
17
18 var (
19 bindir = fs.NewDir(maint.T, "icmd-dir")
20 binname = bindir.Join("bin-stub") + pathext()
21 stubpath = filepath.FromSlash("./internal/stub")
22 )
23
24 func pathext() string {
25 if runtime.GOOS == "windows" {
26 return ".exe"
27 }
28 return ""
29 }
30
31 func TestMain(m *testing.M) {
32 exitcode := m.Run()
33 bindir.Remove()
34 os.Exit(exitcode)
35 }
36
37 func buildStub(t assert.TestingT) {
38 if _, err := os.Stat(binname); err == nil {
39 return
40 }
41 result := RunCommand("go", "build", "-o", binname, stubpath)
42 result.Assert(t, Success)
43 }
44
45 func TestRunCommandSuccess(t *testing.T) {
46 buildStub(t)
47
48 result := RunCommand(binname)
49 result.Assert(t, Success)
50 }
51
52 func TestRunCommandWithCombined(t *testing.T) {
53 buildStub(t)
54
55 result := RunCommand(binname, "-warn")
56 result.Assert(t, Expected{})
57
58 assert.Equal(t, result.Combined(), "this is stdout\nthis is stderr\n")
59 assert.Equal(t, result.Stdout(), "this is stdout\n")
60 assert.Equal(t, result.Stderr(), "this is stderr\n")
61 }
62
63 func TestRunCommandWithTimeoutFinished(t *testing.T) {
64 buildStub(t)
65
66 result := RunCmd(Cmd{
67 Command: []string{binname, "-sleep=1ms"},
68 Timeout: 2 * time.Second,
69 })
70 result.Assert(t, Expected{Out: "this is stdout"})
71 }
72
73 func TestRunCommandWithTimeoutKilled(t *testing.T) {
74 buildStub(t)
75
76 command := []string{binname, "-sleep=200ms"}
77 result := RunCmd(Cmd{Command: command, Timeout: 30 * time.Millisecond})
78 result.Assert(t, Expected{Timeout: true, Out: None, Err: None})
79 }
80
81 func TestRunCommandWithErrors(t *testing.T) {
82 buildStub(t)
83
84 result := RunCommand("doesnotexists")
85 expected := `exec: "doesnotexists": executable file not found`
86 result.Assert(t, Expected{Out: None, Err: None, ExitCode: 127, Error: expected})
87 }
88
89 func TestRunCommandWithStdoutNoStderr(t *testing.T) {
90 buildStub(t)
91
92 result := RunCommand(binname)
93 result.Assert(t, Expected{Out: "this is stdout\n", Err: None})
94 }
95
96 func TestRunCommandWithExitCode(t *testing.T) {
97 buildStub(t)
98
99 result := RunCommand(binname, "-fail=99")
100 result.Assert(t, Expected{
101 ExitCode: 99,
102 Error: "exit status 99",
103 })
104 }
105
106 func TestResult_Match_NotMatched(t *testing.T) {
107 result := &Result{
108 Cmd: exec.Command("binary", "arg1"),
109 ExitCode: 99,
110 Error: errors.New("exit code 99"),
111 outBuffer: newLockedBuffer("the output"),
112 errBuffer: newLockedBuffer("the stderr"),
113 Timeout: true,
114 }
115 exp := Expected{
116 ExitCode: 101,
117 Out: "Something else",
118 Err: None,
119 }
120 err := result.match(exp)
121 assert.ErrorContains(t, err, "Failures")
122 assert.Equal(t, err.Error(), expectedMatch)
123 }
124
125 var expectedMatch = `
126 Command: binary arg1
127 ExitCode: 99 (timeout)
128 Error: exit code 99
129 Stdout: the output
130 Stderr: the stderr
131
132 Failures:
133 ExitCode was 99 expected 101
134 Expected command to finish, but it hit the timeout
135 Expected stdout to contain "Something else"
136 Expected stderr to contain "[NOTHING]"`
137
138 func newLockedBuffer(s string) *lockedBuffer {
139 return &lockedBuffer{buf: *bytes.NewBufferString(s)}
140 }
141
142 func TestResult_Match_NotMatchedNoError(t *testing.T) {
143 result := &Result{
144 Cmd: exec.Command("binary", "arg1"),
145 outBuffer: newLockedBuffer("the output"),
146 errBuffer: newLockedBuffer("the stderr"),
147 }
148 exp := Expected{
149 ExitCode: 101,
150 Out: "Something else",
151 Err: None,
152 }
153 err := result.match(exp)
154 assert.ErrorContains(t, err, "Failures")
155 assert.Equal(t, err.Error(), expectedResultMatchNoMatch)
156 }
157
158 var expectedResultMatchNoMatch = `
159 Command: binary arg1
160 ExitCode: 0
161 Stdout: the output
162 Stderr: the stderr
163
164 Failures:
165 ExitCode was 0 expected 101
166 Expected stdout to contain "Something else"
167 Expected stderr to contain "[NOTHING]"`
168
169 func TestResult_Match_Match(t *testing.T) {
170 result := &Result{
171 Cmd: exec.Command("binary", "arg1"),
172 outBuffer: newLockedBuffer("the output"),
173 errBuffer: newLockedBuffer("the stderr"),
174 }
175 exp := Expected{
176 Out: "the output",
177 Err: "the stderr",
178 }
179 err := result.match(exp)
180 assert.NilError(t, err)
181 }
182
View as plain text